|  | @@ -1,898 +1,7 @@
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -function setAlign(sheet, headers) {
 | 
	
		
			
				|  |  | -    const fuc = () => {
 | 
	
		
			
				|  |  | -        headers.forEach(({ hAlign, vAlign }, index) => {
 | 
	
		
			
				|  |  | -            sheetCommonObj.setAreaAlign(sheet.getRange(-1, index, -1, 1), hAlign, vAlign)
 | 
	
		
			
				|  |  | -        });
 | 
	
		
			
				|  |  | -    };
 | 
	
		
			
				|  |  | -    sheetCommonObj.renderSheetFunc(sheet, fuc);
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -function setFormatter(sheet, headers) {
 | 
	
		
			
				|  |  | -    const fuc = () => {
 | 
	
		
			
				|  |  | -        headers.forEach(({ formatter }, index) => {
 | 
	
		
			
				|  |  | -            if (formatter) {
 | 
	
		
			
				|  |  | -                sheet.setFormatter(-1, index, formatter);
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -        });
 | 
	
		
			
				|  |  | -    };
 | 
	
		
			
				|  |  | -    sheetCommonObj.renderSheetFunc(sheet, fuc);
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -function initSheet(dom, setting) {
 | 
	
		
			
				|  |  | -    const workBook = sheetCommonObj.buildSheet(dom, setting);
 | 
	
		
			
				|  |  | -    const sheet = workBook.getSheet(0);
 | 
	
		
			
				|  |  | -    setAlign(sheet, setting.header);
 | 
	
		
			
				|  |  | -    setFormatter(sheet, setting.header);
 | 
	
		
			
				|  |  | -    return workBook;
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -function showData(sheet, data, headers, emptyRows) {
 | 
	
		
			
				|  |  | -    const fuc = () => {
 | 
	
		
			
				|  |  | -        sheet.setRowCount(data.length);
 | 
	
		
			
				|  |  | -        data.forEach((item, row) => {
 | 
	
		
			
				|  |  | -            headers.forEach(({ dataCode }, col) => {
 | 
	
		
			
				|  |  | -                sheet.setValue(row, col, item[dataCode] || '');
 | 
	
		
			
				|  |  | -            });
 | 
	
		
			
				|  |  | -        });
 | 
	
		
			
				|  |  | -        if (emptyRows) {
 | 
	
		
			
				|  |  | -            sheet.addRows(data.length, emptyRows);
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | -    };
 | 
	
		
			
				|  |  | -    sheetCommonObj.renderSheetFunc(sheet, fuc);
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -const TIME_OUT = 10000;
 | 
	
		
			
				|  |  | -const libID = window.location.search.match(/libID=([^&]+)/)[1];
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -const UpdateType = {
 | 
	
		
			
				|  |  | -    UPDATE: 'update',
 | 
	
		
			
				|  |  | -    DELETE: 'delete',
 | 
	
		
			
				|  |  | -    CREATE: 'create',
 | 
	
		
			
				|  |  | -};
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -const DEBOUNCE_TIME = 200;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -const locked = lockUtil.getLocked();
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -// 地区表
 | 
	
		
			
				|  |  | -const AREA_BOOK = (() => {
 | 
	
		
			
				|  |  | -    const cache = areaList;
 | 
	
		
			
				|  |  | -    const setting = {
 | 
	
		
			
				|  |  | -        header: [
 | 
	
		
			
				|  |  | -            { headerName: '序号', headerWidth: 60, dataCode: 'serialNo', dataType: 'Number', hAlign: 'center', vAlign: 'center' },
 | 
	
		
			
				|  |  | -            { headerName: '地区', headerWidth: $('#area-spread').width() - 80, dataCode: 'name', dataType: 'String', hAlign: 'center', vAlign: 'center' },
 | 
	
		
			
				|  |  | -        ]
 | 
	
		
			
				|  |  | -    };
 | 
	
		
			
				|  |  | -    // 初始化表格
 | 
	
		
			
				|  |  | -    const workBook = initSheet($('#area-spread')[0], setting);
 | 
	
		
			
				|  |  | -    lockUtil.lockSpreads([workBook], locked);
 | 
	
		
			
				|  |  | -    workBook.options.allowExtendPasteRange = false;
 | 
	
		
			
				|  |  | -    workBook.options.allowUserDragDrop = true;
 | 
	
		
			
				|  |  | -    workBook.options.allowUserDragFill = true;
 | 
	
		
			
				|  |  | -    const sheet = workBook.getSheet(0);
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    // 排序显示
 | 
	
		
			
				|  |  | -    cache.sort((a, b) => a.serialNo - b.serialNo);
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    // 显示数据
 | 
	
		
			
				|  |  | -    showData(sheet, cache, setting.header);
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    // 编辑处理
 | 
	
		
			
				|  |  | -    async function handleEdit(changedCells) {
 | 
	
		
			
				|  |  | -        const updateData = [];
 | 
	
		
			
				|  |  | -        let reSort = false;
 | 
	
		
			
				|  |  | -        changedCells.forEach(({ row, col }) => {
 | 
	
		
			
				|  |  | -            const field = setting.header[col].dataCode;
 | 
	
		
			
				|  |  | -            let value = sheet.getValue(row, col);
 | 
	
		
			
				|  |  | -            if (field === 'serialNo') {
 | 
	
		
			
				|  |  | -                reSort = true;
 | 
	
		
			
				|  |  | -                value = +value;
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -            updateData.push({
 | 
	
		
			
				|  |  | -                row,
 | 
	
		
			
				|  |  | -                field,
 | 
	
		
			
				|  |  | -                value,
 | 
	
		
			
				|  |  | -                ID: cache[row].ID,
 | 
	
		
			
				|  |  | -            });
 | 
	
		
			
				|  |  | -        });
 | 
	
		
			
				|  |  | -        try {
 | 
	
		
			
				|  |  | -            await ajaxPost('/priceInfo/editArea', { updateData }, TIME_OUT);
 | 
	
		
			
				|  |  | -            updateData.forEach(({ row, field, value }) => cache[row][field] = value);
 | 
	
		
			
				|  |  | -            if (reSort) {
 | 
	
		
			
				|  |  | -                cache.sort((a, b) => a.serialNo - b.serialNo);
 | 
	
		
			
				|  |  | -                showData(sheet, cache, setting.header);
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -        } catch (err) {
 | 
	
		
			
				|  |  | -            // 恢复各单元格数据
 | 
	
		
			
				|  |  | -            sheetCommonObj.renderSheetFunc(sheet, () => {
 | 
	
		
			
				|  |  | -                changedCells.forEach(({ row, col, field }) => {
 | 
	
		
			
				|  |  | -                    sheet.setValue(row, col, cache[row][field]);
 | 
	
		
			
				|  |  | -                });
 | 
	
		
			
				|  |  | -            });
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -    sheet.bind(GC.Spread.Sheets.Events.ValueChanged, function (e, info) {
 | 
	
		
			
				|  |  | -        const changedCells = [{ row: info.row, col: info.col }];
 | 
	
		
			
				|  |  | -        handleEdit(changedCells);
 | 
	
		
			
				|  |  | -    });
 | 
	
		
			
				|  |  | -    sheet.bind(GC.Spread.Sheets.Events.RangeChanged, function (e, info) {
 | 
	
		
			
				|  |  | -        handleEdit(info.changedCells);
 | 
	
		
			
				|  |  | -    });
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    const curArea = { ID: null };
 | 
	
		
			
				|  |  | -    // 焦点变更处理
 | 
	
		
			
				|  |  | -    const debounceSelectionChanged = _.debounce(function (e, info) {
 | 
	
		
			
				|  |  | -        const row = info.newSelections && info.newSelections[0] ? info.newSelections[0].row : 0;
 | 
	
		
			
				|  |  | -        handleSelectionChanged(row);
 | 
	
		
			
				|  |  | -    }, DEBOUNCE_TIME, { leading: true }); // leading = true : 先触发再延迟
 | 
	
		
			
				|  |  | -    function handleSelectionChanged(row) {
 | 
	
		
			
				|  |  | -        const areaItem = cache[row];
 | 
	
		
			
				|  |  | -        curArea.ID = areaItem && areaItem.ID || null;
 | 
	
		
			
				|  |  | -        CLASS_BOOK.initData(libID, curArea.ID);
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -    sheet.bind(GC.Spread.Sheets.Events.SelectionChanged, debounceSelectionChanged);
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    // 新增
 | 
	
		
			
				|  |  | -    async function insert() {
 | 
	
		
			
				|  |  | -        const data = {
 | 
	
		
			
				|  |  | -            compilationID,
 | 
	
		
			
				|  |  | -            ID: uuid.v1(),
 | 
	
		
			
				|  |  | -            name: '',
 | 
	
		
			
				|  |  | -        };
 | 
	
		
			
				|  |  | -        try {
 | 
	
		
			
				|  |  | -            $.bootstrapLoading.start();
 | 
	
		
			
				|  |  | -            await ajaxPost('/priceInfo/insertArea', { insertData: [data] });
 | 
	
		
			
				|  |  | -            // 新增的数据总是添加在最后
 | 
	
		
			
				|  |  | -            sheet.addRows(cache.length, 1);
 | 
	
		
			
				|  |  | -            cache.push(data);
 | 
	
		
			
				|  |  | -            const lastRow = cache.length - 1;
 | 
	
		
			
				|  |  | -            sheet.setSelection(lastRow, 0, 1, 1);
 | 
	
		
			
				|  |  | -            sheet.showRow(lastRow, GC.Spread.Sheets.VerticalPosition.top);
 | 
	
		
			
				|  |  | -            handleSelectionChanged(lastRow);
 | 
	
		
			
				|  |  | -        } catch (err) {
 | 
	
		
			
				|  |  | -            alert(err);
 | 
	
		
			
				|  |  | -        } finally {
 | 
	
		
			
				|  |  | -            $.bootstrapLoading.end();
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    // 删除
 | 
	
		
			
				|  |  | -    async function del() {
 | 
	
		
			
				|  |  | -        try {
 | 
	
		
			
				|  |  | -            $.bootstrapLoading.start();
 | 
	
		
			
				|  |  | -            await ajaxPost('/priceInfo/deleteArea', { deleteData: [curArea.ID] });
 | 
	
		
			
				|  |  | -            const index = cache.findIndex(item => item.ID === curArea.ID);
 | 
	
		
			
				|  |  | -            sheet.deleteRows(index, 1);
 | 
	
		
			
				|  |  | -            cache.splice(index, 1);
 | 
	
		
			
				|  |  | -            const row = sheet.getActiveRowIndex();
 | 
	
		
			
				|  |  | -            handleSelectionChanged(row);
 | 
	
		
			
				|  |  | -        } catch (err) {
 | 
	
		
			
				|  |  | -            alert(err);
 | 
	
		
			
				|  |  | -        } finally {
 | 
	
		
			
				|  |  | -            $.bootstrapLoading.end();
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    // 右键功能
 | 
	
		
			
				|  |  | -    function buildContextMenu() {
 | 
	
		
			
				|  |  | -        $.contextMenu({
 | 
	
		
			
				|  |  | -            selector: '#area-spread',
 | 
	
		
			
				|  |  | -            build: function ($triggerElement, e) {
 | 
	
		
			
				|  |  | -                // 控制允许右键菜单在哪个位置出现
 | 
	
		
			
				|  |  | -                const offset = $('#area-spread').offset();
 | 
	
		
			
				|  |  | -                const x = e.pageX - offset.left;
 | 
	
		
			
				|  |  | -                const y = e.pageY - offset.top;
 | 
	
		
			
				|  |  | -                const target = sheet.hitTest(x, y);
 | 
	
		
			
				|  |  | -                if (target.hitTestType === 3) { // 在表格内
 | 
	
		
			
				|  |  | -                    const sel = sheet.getSelections()[0];
 | 
	
		
			
				|  |  | -                    if (sel && sel.rowCount === 1 && typeof target.row !== 'undefined') {
 | 
	
		
			
				|  |  | -                        const orgRow = sheet.getActiveRowIndex();
 | 
	
		
			
				|  |  | -                        if (orgRow !== target.row) {
 | 
	
		
			
				|  |  | -                            sheet.setActiveCell(target.row, target.col);
 | 
	
		
			
				|  |  | -                            handleSelectionChanged(target.row);
 | 
	
		
			
				|  |  | -                        }
 | 
	
		
			
				|  |  | -                    }
 | 
	
		
			
				|  |  | -                    return {
 | 
	
		
			
				|  |  | -                        items: {
 | 
	
		
			
				|  |  | -                            insert: {
 | 
	
		
			
				|  |  | -                                name: '新增',
 | 
	
		
			
				|  |  | -                                icon: "fa-arrow-left",
 | 
	
		
			
				|  |  | -                                disabled: function () {
 | 
	
		
			
				|  |  | -                                    return locked;
 | 
	
		
			
				|  |  | -                                },
 | 
	
		
			
				|  |  | -                                callback: function (key, opt) {
 | 
	
		
			
				|  |  | -                                    insert();
 | 
	
		
			
				|  |  | -                                }
 | 
	
		
			
				|  |  | -                            },
 | 
	
		
			
				|  |  | -                            del: {
 | 
	
		
			
				|  |  | -                                name: '删除',
 | 
	
		
			
				|  |  | -                                icon: "fa-arrow-left",
 | 
	
		
			
				|  |  | -                                disabled: function () {
 | 
	
		
			
				|  |  | -                                    return locked || !cache[target.row];
 | 
	
		
			
				|  |  | -                                },
 | 
	
		
			
				|  |  | -                                callback: function (key, opt) {
 | 
	
		
			
				|  |  | -                                    del();
 | 
	
		
			
				|  |  | -                                }
 | 
	
		
			
				|  |  | -                            },
 | 
	
		
			
				|  |  | -                        }
 | 
	
		
			
				|  |  | -                    };
 | 
	
		
			
				|  |  | -                }
 | 
	
		
			
				|  |  | -                else {
 | 
	
		
			
				|  |  | -                    return false;
 | 
	
		
			
				|  |  | -                }
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -        });
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -    buildContextMenu();
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    return {
 | 
	
		
			
				|  |  | -        handleSelectionChanged,
 | 
	
		
			
				|  |  | -        curArea,
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -})();
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -// 分类表
 | 
	
		
			
				|  |  | -const CLASS_BOOK = (() => {
 | 
	
		
			
				|  |  | -    const setting = {
 | 
	
		
			
				|  |  | -        header: [{ headerName: '分类', headerWidth: $('#area-spread').width(), dataCode: 'name', dataType: 'String', hAlign: 'left', vAlign: 'center' }],
 | 
	
		
			
				|  |  | -        controller: {
 | 
	
		
			
				|  |  | -            cols: [
 | 
	
		
			
				|  |  | -                {
 | 
	
		
			
				|  |  | -                    data: {
 | 
	
		
			
				|  |  | -                        field: 'name',
 | 
	
		
			
				|  |  | -                        vAlign: 1,
 | 
	
		
			
				|  |  | -                        hAlign: 0,
 | 
	
		
			
				|  |  | -                        font: 'Arial'
 | 
	
		
			
				|  |  | -                    },
 | 
	
		
			
				|  |  | -                }
 | 
	
		
			
				|  |  | -            ],
 | 
	
		
			
				|  |  | -            headRows: 1,
 | 
	
		
			
				|  |  | -            headRowHeight: [30],
 | 
	
		
			
				|  |  | -            emptyRows: 0,
 | 
	
		
			
				|  |  | -            treeCol: 0
 | 
	
		
			
				|  |  | -        },
 | 
	
		
			
				|  |  | -        tree: {
 | 
	
		
			
				|  |  | -            id: 'ID',
 | 
	
		
			
				|  |  | -            pid: 'ParentID',
 | 
	
		
			
				|  |  | -            nid: 'NextSiblingID',
 | 
	
		
			
				|  |  | -            rootId: -1
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | -    };
 | 
	
		
			
				|  |  | -    // 初始化表格
 | 
	
		
			
				|  |  | -    const workBook = initSheet($('#class-spread')[0], setting);
 | 
	
		
			
				|  |  | -    workBook.options.allowExtendPasteRange = false;
 | 
	
		
			
				|  |  | -    workBook.options.allowUserDragDrop = true;
 | 
	
		
			
				|  |  | -    workBook.options.allowUserDragFill = true;
 | 
	
		
			
				|  |  | -    const sheet = workBook.getSheet(0);
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    let tree;
 | 
	
		
			
				|  |  | -    let controller;
 | 
	
		
			
				|  |  | -    // 初始化数据
 | 
	
		
			
				|  |  | -    async function initData(libID, areaID) {
 | 
	
		
			
				|  |  | -        if (!areaID) {
 | 
	
		
			
				|  |  | -            tree = null;
 | 
	
		
			
				|  |  | -            controller = null;
 | 
	
		
			
				|  |  | -            sheet.setRowCount(0);
 | 
	
		
			
				|  |  | -            PRICE_BOOK.clear();
 | 
	
		
			
				|  |  | -            return;
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | -        $.bootstrapLoading.start();
 | 
	
		
			
				|  |  | -        try {
 | 
	
		
			
				|  |  | -            const data = await ajaxPost('/priceInfo/getClassData', { libID, areaID }, TIME_OUT);
 | 
	
		
			
				|  |  | -            tree = idTree.createNew(setting.tree);
 | 
	
		
			
				|  |  | -            tree.loadDatas(data);
 | 
	
		
			
				|  |  | -            tree.selected = tree.items.length > 0 ? tree.items[0] : null;
 | 
	
		
			
				|  |  | -            controller = TREE_SHEET_CONTROLLER.createNew(tree, sheet, setting.controller, false);
 | 
	
		
			
				|  |  | -            controller.showTreeData();
 | 
	
		
			
				|  |  | -            handleSelectionChanged(0);
 | 
	
		
			
				|  |  | -            sheet.setSelection(0, 0, 1, 1);
 | 
	
		
			
				|  |  | -            lockUtil.lockSpreads([workBook], locked);
 | 
	
		
			
				|  |  | -        } catch (err) {
 | 
	
		
			
				|  |  | -            console.log(err);
 | 
	
		
			
				|  |  | -            tree = null;
 | 
	
		
			
				|  |  | -            controller = null;
 | 
	
		
			
				|  |  | -            sheet.setRowCount(0);
 | 
	
		
			
				|  |  | -            alert(err);
 | 
	
		
			
				|  |  | -        } finally {
 | 
	
		
			
				|  |  | -            $.bootstrapLoading.end();
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    // 编辑处理
 | 
	
		
			
				|  |  | -    async function handleEdit(changedCells) {
 | 
	
		
			
				|  |  | -        const updateData = [];
 | 
	
		
			
				|  |  | -        changedCells.forEach(({ row, col }) => {
 | 
	
		
			
				|  |  | -            updateData.push({
 | 
	
		
			
				|  |  | -                row,
 | 
	
		
			
				|  |  | -                type: UpdateType.UPDATE,
 | 
	
		
			
				|  |  | -                filter: { ID: tree.items[row].data.ID },
 | 
	
		
			
				|  |  | -                update: { name: sheet.getValue(row, col) }
 | 
	
		
			
				|  |  | -            });
 | 
	
		
			
				|  |  | -        });
 | 
	
		
			
				|  |  | -        try {
 | 
	
		
			
				|  |  | -            await ajaxPost('/priceInfo/editClassData', { updateData }, TIME_OUT);
 | 
	
		
			
				|  |  | -            updateData.forEach(({ row, update: { name } }) => tree.items[row].data.name = name);
 | 
	
		
			
				|  |  | -        } catch (err) {
 | 
	
		
			
				|  |  | -            // 恢复各单元格数据
 | 
	
		
			
				|  |  | -            sheetCommonObj.renderSheetFunc(sheet, () => {
 | 
	
		
			
				|  |  | -                changedCells.forEach(({ row }) => {
 | 
	
		
			
				|  |  | -                    sheet.setValue(tree.items[row].data.name);
 | 
	
		
			
				|  |  | -                });
 | 
	
		
			
				|  |  | -            });
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -    sheet.bind(GC.Spread.Sheets.Events.ValueChanged, function (e, info) {
 | 
	
		
			
				|  |  | -        const changedCells = [{ row: info.row, col: info.col }];
 | 
	
		
			
				|  |  | -        handleEdit(changedCells);
 | 
	
		
			
				|  |  | -    });
 | 
	
		
			
				|  |  | -    sheet.bind(GC.Spread.Sheets.Events.RangeChanged, function (e, info) {
 | 
	
		
			
				|  |  | -        handleEdit(info.changedCells);
 | 
	
		
			
				|  |  | -    });
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    // 树操作相关
 | 
	
		
			
				|  |  | -    const $insert = $('#tree-insert');
 | 
	
		
			
				|  |  | -    const $remove = $('#tree-remove');
 | 
	
		
			
				|  |  | -    const $upLevel = $('#tree-up-level');
 | 
	
		
			
				|  |  | -    const $downLevel = $('#tree-down-level');
 | 
	
		
			
				|  |  | -    const $downMove = $('#tree-down-move');
 | 
	
		
			
				|  |  | -    const $upMove = $('#tree-up-move');
 | 
	
		
			
				|  |  | -    const $calcPriceIndex = $('#calc-price-index');
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    // 插入
 | 
	
		
			
				|  |  | -    let canInsert = true;
 | 
	
		
			
				|  |  | -    async function insert() {
 | 
	
		
			
				|  |  | -        try {
 | 
	
		
			
				|  |  | -            if (!canInsert) {
 | 
	
		
			
				|  |  | -                return false;
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -            canInsert = false;
 | 
	
		
			
				|  |  | -            $.bootstrapLoading.start();
 | 
	
		
			
				|  |  | -            const updateData = [];
 | 
	
		
			
				|  |  | -            const selected = tree.selected;
 | 
	
		
			
				|  |  | -            const newItem = {
 | 
	
		
			
				|  |  | -                libID,
 | 
	
		
			
				|  |  | -                areaID: AREA_BOOK.curArea.ID,
 | 
	
		
			
				|  |  | -                ID: uuid.v1(),
 | 
	
		
			
				|  |  | -                name: '',
 | 
	
		
			
				|  |  | -                ParentID: '-1',
 | 
	
		
			
				|  |  | -                NextSiblingID: '-1'
 | 
	
		
			
				|  |  | -            };
 | 
	
		
			
				|  |  | -            if (selected) {
 | 
	
		
			
				|  |  | -                newItem.ParentID = selected.data.ParentID;
 | 
	
		
			
				|  |  | -                updateData.push({
 | 
	
		
			
				|  |  | -                    type: UpdateType.UPDATE,
 | 
	
		
			
				|  |  | -                    filter: { ID: selected.data.ID },
 | 
	
		
			
				|  |  | -                    update: { NextSiblingID: newItem.ID }
 | 
	
		
			
				|  |  | -                });
 | 
	
		
			
				|  |  | -                if (selected.nextSibling) {
 | 
	
		
			
				|  |  | -                    newItem.NextSiblingID = selected.nextSibling.data.ID;
 | 
	
		
			
				|  |  | -                }
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -            updateData.push({
 | 
	
		
			
				|  |  | -                type: UpdateType.CREATE,
 | 
	
		
			
				|  |  | -                document: newItem
 | 
	
		
			
				|  |  | -            });
 | 
	
		
			
				|  |  | -            await ajaxPost('/priceInfo/editClassData', { updateData });
 | 
	
		
			
				|  |  | -            controller.insertByID(newItem.ID);
 | 
	
		
			
				|  |  | -            handleSelectionChanged(sheet.getActiveRowIndex());
 | 
	
		
			
				|  |  | -        } catch (err) {
 | 
	
		
			
				|  |  | -            console.log(err);
 | 
	
		
			
				|  |  | -            alert(err);
 | 
	
		
			
				|  |  | -        } finally {
 | 
	
		
			
				|  |  | -            canInsert = true;
 | 
	
		
			
				|  |  | -            $.bootstrapLoading.end();
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    $insert.click(_.debounce(insert, DEBOUNCE_TIME, { leading: true }));
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    // 删除
 | 
	
		
			
				|  |  | -    let canRemove = true;
 | 
	
		
			
				|  |  | -    async function remove() {
 | 
	
		
			
				|  |  | -        try {
 | 
	
		
			
				|  |  | -            if (!canRemove) {
 | 
	
		
			
				|  |  | -                return false;
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -            canRemove = false;
 | 
	
		
			
				|  |  | -            $.bootstrapLoading.start();
 | 
	
		
			
				|  |  | -            const updateData = [];
 | 
	
		
			
				|  |  | -            const selected = tree.selected;
 | 
	
		
			
				|  |  | -            const children = selected.getPosterity();
 | 
	
		
			
				|  |  | -            [selected, ...children].forEach(node => updateData.push({
 | 
	
		
			
				|  |  | -                type: UpdateType.DELETE,
 | 
	
		
			
				|  |  | -                filter: { ID: node.data.ID }
 | 
	
		
			
				|  |  | -            }));
 | 
	
		
			
				|  |  | -            if (selected.preSibling) {
 | 
	
		
			
				|  |  | -                updateData.push({
 | 
	
		
			
				|  |  | -                    type: UpdateType.UPDATE,
 | 
	
		
			
				|  |  | -                    filter: { ID: selected.preSibling.data.ID },
 | 
	
		
			
				|  |  | -                    update: { NextSiblingID: selected.data.NextSiblingID }
 | 
	
		
			
				|  |  | -                });
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -            await ajaxPost('/priceInfo/editClassData', { updateData });
 | 
	
		
			
				|  |  | -            controller.delete();
 | 
	
		
			
				|  |  | -            handleSelectionChanged(sheet.getActiveRowIndex());
 | 
	
		
			
				|  |  | -        } catch (err) {
 | 
	
		
			
				|  |  | -            alert(err);
 | 
	
		
			
				|  |  | -        } finally {
 | 
	
		
			
				|  |  | -            canRemove = true;
 | 
	
		
			
				|  |  | -            $.bootstrapLoading.end();
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    $remove.click(_.debounce(remove, DEBOUNCE_TIME, { leading: true }));
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    // 升级
 | 
	
		
			
				|  |  | -    let canUpLevel = true;
 | 
	
		
			
				|  |  | -    async function upLevel() {
 | 
	
		
			
				|  |  | -        try {
 | 
	
		
			
				|  |  | -            if (!canUpLevel) {
 | 
	
		
			
				|  |  | -                return false;
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -            canUpLevel = false;
 | 
	
		
			
				|  |  | -            $.bootstrapLoading.start();
 | 
	
		
			
				|  |  | -            const updateData = [];
 | 
	
		
			
				|  |  | -            const selected = tree.selected;
 | 
	
		
			
				|  |  | -            if (selected.preSibling) {
 | 
	
		
			
				|  |  | -                updateData.push({
 | 
	
		
			
				|  |  | -                    type: UpdateType.UPDATE,
 | 
	
		
			
				|  |  | -                    filter: { ID: selected.preSibling.data.ID },
 | 
	
		
			
				|  |  | -                    update: { NextSiblingID: -1 }
 | 
	
		
			
				|  |  | -                });
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -            if (selected.parent) {
 | 
	
		
			
				|  |  | -                updateData.push({
 | 
	
		
			
				|  |  | -                    type: UpdateType.UPDATE,
 | 
	
		
			
				|  |  | -                    filter: { ID: selected.parent.data.ID },
 | 
	
		
			
				|  |  | -                    update: { NextSiblingID: selected.data.ID }
 | 
	
		
			
				|  |  | -                });
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -            updateData.push({
 | 
	
		
			
				|  |  | -                type: UpdateType.UPDATE,
 | 
	
		
			
				|  |  | -                filter: { ID: selected.data.ID },
 | 
	
		
			
				|  |  | -                update: { ParentID: selected.parent.data.ParentID, NextSiblingID: selected.parent.data.NextSiblingID }
 | 
	
		
			
				|  |  | -            });
 | 
	
		
			
				|  |  | -            let curNode = selected.nextSibling;
 | 
	
		
			
				|  |  | -            while (curNode) {
 | 
	
		
			
				|  |  | -                updateData.push({
 | 
	
		
			
				|  |  | -                    type: UpdateType.UPDATE,
 | 
	
		
			
				|  |  | -                    filter: { ID: curNode.data.ID },
 | 
	
		
			
				|  |  | -                    update: { ParentID: selected.data.ID }
 | 
	
		
			
				|  |  | -                });
 | 
	
		
			
				|  |  | -                curNode = curNode.nextSibling;
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -            await ajaxPost('/priceInfo/editClassData', { updateData });
 | 
	
		
			
				|  |  | -            controller.upLevel();
 | 
	
		
			
				|  |  | -            refreshTreeButton(tree.selected);
 | 
	
		
			
				|  |  | -        } catch (err) {
 | 
	
		
			
				|  |  | -            alert(err);
 | 
	
		
			
				|  |  | -        } finally {
 | 
	
		
			
				|  |  | -            canUpLevel = true;
 | 
	
		
			
				|  |  | -            $.bootstrapLoading.end();
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    $upLevel.click(_.debounce(upLevel, DEBOUNCE_TIME, { leading: true }));
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    // 降级
 | 
	
		
			
				|  |  | -    let canDownLevel = true;
 | 
	
		
			
				|  |  | -    async function downLevel() {
 | 
	
		
			
				|  |  | -        try {
 | 
	
		
			
				|  |  | -            if (!canDownLevel) {
 | 
	
		
			
				|  |  | -                return false;
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -            canDownLevel = false;
 | 
	
		
			
				|  |  | -            $.bootstrapLoading.start();
 | 
	
		
			
				|  |  | -            const updateData = [];
 | 
	
		
			
				|  |  | -            const selected = tree.selected;
 | 
	
		
			
				|  |  | -            if (selected.preSibling) {
 | 
	
		
			
				|  |  | -                updateData.push({
 | 
	
		
			
				|  |  | -                    type: UpdateType.UPDATE,
 | 
	
		
			
				|  |  | -                    filter: { ID: selected.preSibling.data.ID },
 | 
	
		
			
				|  |  | -                    update: { NextSiblingID: selected.data.NextSiblingID }
 | 
	
		
			
				|  |  | -                });
 | 
	
		
			
				|  |  | -                const preSiblingLastChild = selected.preSibling.children[selected.preSibling.children.length - 1];
 | 
	
		
			
				|  |  | -                if (preSiblingLastChild) {
 | 
	
		
			
				|  |  | -                    updateData.push({
 | 
	
		
			
				|  |  | -                        type: UpdateType.UPDATE,
 | 
	
		
			
				|  |  | -                        filter: { ID: preSiblingLastChild.data.ID },
 | 
	
		
			
				|  |  | -                        update: { NextSiblingID: selected.data.ID }
 | 
	
		
			
				|  |  | -                    });
 | 
	
		
			
				|  |  | -                }
 | 
	
		
			
				|  |  | -                updateData.push({
 | 
	
		
			
				|  |  | -                    type: UpdateType.UPDATE,
 | 
	
		
			
				|  |  | -                    filter: { ID: selected.data.ID },
 | 
	
		
			
				|  |  | -                    update: { ParentID: selected.preSibling.data.ID, NextSiblingID: -1 }
 | 
	
		
			
				|  |  | -                });
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -            await ajaxPost('/priceInfo/editClassData', { updateData });
 | 
	
		
			
				|  |  | -            controller.downLevel();
 | 
	
		
			
				|  |  | -            refreshTreeButton(tree.selected);
 | 
	
		
			
				|  |  | -        } catch (err) {
 | 
	
		
			
				|  |  | -            alert(err);
 | 
	
		
			
				|  |  | -        } finally {
 | 
	
		
			
				|  |  | -            canDownLevel = true;
 | 
	
		
			
				|  |  | -            $.bootstrapLoading.end();
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    $downLevel.click(_.debounce(downLevel, DEBOUNCE_TIME, { leading: true }));
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    // 下移
 | 
	
		
			
				|  |  | -    let canDownMove = true;
 | 
	
		
			
				|  |  | -    async function downMove() {
 | 
	
		
			
				|  |  | -        try {
 | 
	
		
			
				|  |  | -            if (!canDownMove) {
 | 
	
		
			
				|  |  | -                return false;
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -            canDownMove = false;
 | 
	
		
			
				|  |  | -            $.bootstrapLoading.start();
 | 
	
		
			
				|  |  | -            const updateData = [];
 | 
	
		
			
				|  |  | -            const selected = tree.selected;
 | 
	
		
			
				|  |  | -            if (selected.preSibling) {
 | 
	
		
			
				|  |  | -                updateData.push({
 | 
	
		
			
				|  |  | -                    type: UpdateType.UPDATE,
 | 
	
		
			
				|  |  | -                    filter: { ID: selected.preSibling.data.ID },
 | 
	
		
			
				|  |  | -                    update: { NextSiblingID: selected.data.NextSiblingID }
 | 
	
		
			
				|  |  | -                });
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -            updateData.push({
 | 
	
		
			
				|  |  | -                type: UpdateType.UPDATE,
 | 
	
		
			
				|  |  | -                filter: { ID: selected.data.ID },
 | 
	
		
			
				|  |  | -                update: { NextSiblingID: selected.nextSibling.data.NextSiblingID }
 | 
	
		
			
				|  |  | -            });
 | 
	
		
			
				|  |  | -            updateData.push({
 | 
	
		
			
				|  |  | -                type: UpdateType.UPDATE,
 | 
	
		
			
				|  |  | -                filter: { ID: selected.nextSibling.data.ID },
 | 
	
		
			
				|  |  | -                update: { NextSiblingID: selected.data.ID }
 | 
	
		
			
				|  |  | -            });
 | 
	
		
			
				|  |  | -            await ajaxPost('/priceInfo/editClassData', { updateData });
 | 
	
		
			
				|  |  | -            controller.downMove();
 | 
	
		
			
				|  |  | -            refreshTreeButton(tree.selected);
 | 
	
		
			
				|  |  | -        } catch (err) {
 | 
	
		
			
				|  |  | -            alert(err);
 | 
	
		
			
				|  |  | -        } finally {
 | 
	
		
			
				|  |  | -            canDownMove = true;
 | 
	
		
			
				|  |  | -            $.bootstrapLoading.end();
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    $downMove.click(_.debounce(downMove, DEBOUNCE_TIME, { leading: true }));
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    // 上移
 | 
	
		
			
				|  |  | -    let canUpMove = true;
 | 
	
		
			
				|  |  | -    async function upMove() {
 | 
	
		
			
				|  |  | -        try {
 | 
	
		
			
				|  |  | -            if (!canUpMove) {
 | 
	
		
			
				|  |  | -                return false;
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -            canUpMove = false;
 | 
	
		
			
				|  |  | -            $.bootstrapLoading.start();
 | 
	
		
			
				|  |  | -            const updateData = [];
 | 
	
		
			
				|  |  | -            const selected = tree.selected;
 | 
	
		
			
				|  |  | -            if (selected.preSibling) {
 | 
	
		
			
				|  |  | -                updateData.push({
 | 
	
		
			
				|  |  | -                    type: UpdateType.UPDATE,
 | 
	
		
			
				|  |  | -                    filter: { ID: selected.preSibling.data.ID },
 | 
	
		
			
				|  |  | -                    update: { NextSiblingID: selected.data.NextSiblingID }
 | 
	
		
			
				|  |  | -                });
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -            const prePreSibling = selected.preSibling.preSibling;
 | 
	
		
			
				|  |  | -            if (prePreSibling) {
 | 
	
		
			
				|  |  | -                updateData.push({
 | 
	
		
			
				|  |  | -                    type: UpdateType.UPDATE,
 | 
	
		
			
				|  |  | -                    filter: { ID: prePreSibling.data.ID },
 | 
	
		
			
				|  |  | -                    update: { NextSiblingID: selected.data.ID }
 | 
	
		
			
				|  |  | -                });
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -            updateData.push({
 | 
	
		
			
				|  |  | -                type: UpdateType.UPDATE,
 | 
	
		
			
				|  |  | -                filter: { ID: selected.data.ID },
 | 
	
		
			
				|  |  | -                update: { NextSiblingID: selected.preSibling.data.ID }
 | 
	
		
			
				|  |  | -            });
 | 
	
		
			
				|  |  | -            await ajaxPost('/priceInfo/editClassData', { updateData });
 | 
	
		
			
				|  |  | -            controller.upMove();
 | 
	
		
			
				|  |  | -            refreshTreeButton(tree.selected);
 | 
	
		
			
				|  |  | -        } catch (err) {
 | 
	
		
			
				|  |  | -            alert(err);
 | 
	
		
			
				|  |  | -        } finally {
 | 
	
		
			
				|  |  | -            canUpMove = true;
 | 
	
		
			
				|  |  | -            $.bootstrapLoading.end();
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    $upMove.click(_.debounce(upMove, DEBOUNCE_TIME, { leading: true }));
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    // 刷新树操作按钮有效性
 | 
	
		
			
				|  |  | -    function refreshTreeButton(selected) {
 | 
	
		
			
				|  |  | -        if (locked) {
 | 
	
		
			
				|  |  | -            return;
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | -        $insert.removeClass('disabled');
 | 
	
		
			
				|  |  | -        $remove.removeClass('disabled');
 | 
	
		
			
				|  |  | -        $upLevel.removeClass('disabled');
 | 
	
		
			
				|  |  | -        $downLevel.removeClass('disabled');
 | 
	
		
			
				|  |  | -        $downMove.removeClass('disabled');
 | 
	
		
			
				|  |  | -        $upMove.removeClass('disabled');
 | 
	
		
			
				|  |  | -        if (!selected) {
 | 
	
		
			
				|  |  | -            $remove.addClass('disabled');
 | 
	
		
			
				|  |  | -            $upLevel.addClass('disabled');
 | 
	
		
			
				|  |  | -            $downLevel.addClass('disabled');
 | 
	
		
			
				|  |  | -            $downMove.addClass('disabled');
 | 
	
		
			
				|  |  | -            $upMove.addClass('disabled');
 | 
	
		
			
				|  |  | -        } else {
 | 
	
		
			
				|  |  | -            if (!selected.preSibling) {
 | 
	
		
			
				|  |  | -                $downLevel.addClass('disabled');
 | 
	
		
			
				|  |  | -                $upMove.addClass('disabled');
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -            if (!selected.nextSibling) {
 | 
	
		
			
				|  |  | -                $downMove.addClass('disabled');
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -            if (!selected.parent) {
 | 
	
		
			
				|  |  | -                $upLevel.addClass('disabled');
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    // 焦点变更处理
 | 
	
		
			
				|  |  | -    const curClass = { ID: null };
 | 
	
		
			
				|  |  | -    function handleSelectionChanged(row) {
 | 
	
		
			
				|  |  | -        const classNode = tree.items[row] || null;
 | 
	
		
			
				|  |  | -        tree.selected = classNode;
 | 
	
		
			
				|  |  | -        refreshTreeButton(classNode);
 | 
	
		
			
				|  |  | -        curClass.ID = classNode && classNode.data && classNode.data.ID || null;
 | 
	
		
			
				|  |  | -        const classIDList = []
 | 
	
		
			
				|  |  | -        if (classNode) {
 | 
	
		
			
				|  |  | -            classIDList.push(classNode.data.ID);
 | 
	
		
			
				|  |  | -            const children = classNode.getPosterity();
 | 
	
		
			
				|  |  | -            children.forEach(child => classIDList.push(child.data.ID));
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | -        PRICE_BOOK.initData(classIDList);
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -    const debounceSelectionChanged = _.debounce(function (e, info) {
 | 
	
		
			
				|  |  | -        const row = info.newSelections && info.newSelections[0] ? info.newSelections[0].row : 0;
 | 
	
		
			
				|  |  | -        handleSelectionChanged(row);
 | 
	
		
			
				|  |  | -    }, DEBOUNCE_TIME, { leading: true });
 | 
	
		
			
				|  |  | -    sheet.bind(GC.Spread.Sheets.Events.SelectionChanged, debounceSelectionChanged);
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    $calcPriceIndex.click(_.debounce(async () => {
 | 
	
		
			
				|  |  | -        $.bootstrapLoading.start();
 | 
	
		
			
				|  |  | -        try {
 | 
	
		
			
				|  |  | -            const data = await ajaxPost('/priceInfo/calcPriceIndex', { libID, period: curLibPeriod, compilationID }, TIME_OUT);
 | 
	
		
			
				|  |  | -            //alert(data);
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -            if (data) {
 | 
	
		
			
				|  |  | -                const htmlStr = data.replace(/\n/gm, '<br>'); //replaceAll('\n','<br>',data);
 | 
	
		
			
				|  |  | -                $("#result-info-body").html(htmlStr);
 | 
	
		
			
				|  |  | -                $("#result-info").modal('show');
 | 
	
		
			
				|  |  | -            } else {
 | 
	
		
			
				|  |  | -                alert('计算完成!')
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -        } catch (error) {
 | 
	
		
			
				|  |  | -            console.log(error);
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | -        $.bootstrapLoading.end();
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    }, DEBOUNCE_TIME, { leading: true }));
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    return {
 | 
	
		
			
				|  |  | -        initData,
 | 
	
		
			
				|  |  | -        handleSelectionChanged,
 | 
	
		
			
				|  |  | -        curClass,
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -})();
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -// 关键字表
 | 
	
		
			
				|  |  | -const KEYWORD_BOOK = (() => {
 | 
	
		
			
				|  |  | -    const setting = {
 | 
	
		
			
				|  |  | -        header: [
 | 
	
		
			
				|  |  | -            { headerName: '关键字', headerWidth: 200, dataCode: 'keyword', dataType: 'String', hAlign: 'left', vAlign: 'center' },
 | 
	
		
			
				|  |  | -            { headerName: '单位', headerWidth: 70, dataCode: 'unit', dataType: 'String', hAlign: 'center', vAlign: 'center' },
 | 
	
		
			
				|  |  | -            { headerName: '关键字效果', headerWidth: 100, dataCode: 'coe', dataType: 'String', hAlign: 'center', vAlign: 'center' },
 | 
	
		
			
				|  |  | -            { headerName: '组别', headerWidth: 50, dataCode: 'group', dataType: 'String', hAlign: 'center', vAlign: 'center' },
 | 
	
		
			
				|  |  | -            { headerName: '选项号', headerWidth: 70, dataCode: 'optionCode', dataType: 'String', hAlign: 'center', vAlign: 'center' },
 | 
	
		
			
				|  |  | -        ],
 | 
	
		
			
				|  |  | -    };
 | 
	
		
			
				|  |  | -    // 初始化表格
 | 
	
		
			
				|  |  | -    const workBook = initSheet($('#keyword-spread')[0], setting);
 | 
	
		
			
				|  |  | -    workBook.options.allowUserDragDrop = false;
 | 
	
		
			
				|  |  | -    workBook.options.allowUserDragFill = false;
 | 
	
		
			
				|  |  | -    lockUtil.lockSpreads([workBook], true);
 | 
	
		
			
				|  |  | -    const sheet = workBook.getSheet(0);
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    // 显示关键字数据
 | 
	
		
			
				|  |  | -    const showKeywordData = (keywordList) => {
 | 
	
		
			
				|  |  | -        showData(sheet, keywordList, setting.header);
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    return {
 | 
	
		
			
				|  |  | -        showKeywordData
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -})();
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -// 价格信息表
 | 
	
		
			
				|  |  | -const PRICE_BOOK = (() => {
 | 
	
		
			
				|  |  | -    const setting = {
 | 
	
		
			
				|  |  | -        header: [
 | 
	
		
			
				|  |  | -            { headerName: '编码', headerWidth: 100, dataCode: 'code', dataType: 'String', hAlign: 'left', vAlign: 'center', formatter: "@" },
 | 
	
		
			
				|  |  | -            { headerName: '别名编码', headerWidth: 70, dataCode: 'classCode', dataType: 'String', hAlign: 'left', vAlign: 'center', formatter: "@" },
 | 
	
		
			
				|  |  | -            { headerName: '名称', headerWidth: 200, dataCode: 'name', dataType: 'String', hAlign: 'left', vAlign: 'center' },
 | 
	
		
			
				|  |  | -            { headerName: '规格型号', headerWidth: 120, dataCode: 'specs', dataType: 'String', hAlign: 'left', vAlign: 'center' },
 | 
	
		
			
				|  |  | -            { headerName: '单位', headerWidth: 80, dataCode: 'unit', dataType: 'String', hAlign: 'center', vAlign: 'center' },
 | 
	
		
			
				|  |  | -            { headerName: '不含税价', headerWidth: 80, dataCode: 'noTaxPrice', dataType: 'String', hAlign: 'right', vAlign: 'center' },
 | 
	
		
			
				|  |  | -            { headerName: '含税价', headerWidth: 80, dataCode: 'taxPrice', dataType: 'String', hAlign: 'right', vAlign: 'center' },
 | 
	
		
			
				|  |  | -            { headerName: '月份备注', headerWidth: 140, dataCode: 'dateRemark', dataType: 'String', hAlign: 'left', vAlign: 'center' },
 | 
	
		
			
				|  |  | -            { headerName: '计算式', headerWidth: 100, dataCode: 'expString', dataType: 'String', hAlign: 'left', vAlign: 'center' },
 | 
	
		
			
				|  |  | -        ],
 | 
	
		
			
				|  |  | -    };
 | 
	
		
			
				|  |  | -    // 初始化表格
 | 
	
		
			
				|  |  | -    const workBook = initSheet($('#price-spread')[0], setting);
 | 
	
		
			
				|  |  | -    workBook.options.allowUserDragDrop = true;
 | 
	
		
			
				|  |  | -    workBook.options.allowUserDragFill = true;
 | 
	
		
			
				|  |  | -    lockUtil.lockSpreads([workBook], locked);
 | 
	
		
			
				|  |  | -    const sheet = workBook.getSheet(0);
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    let cache = [];
 | 
	
		
			
				|  |  | -    // 清空
 | 
	
		
			
				|  |  | -    function clear() {
 | 
	
		
			
				|  |  | -        cache = [];
 | 
	
		
			
				|  |  | -        sheet.setRowCount(0);
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -    // 初始化数据
 | 
	
		
			
				|  |  | -    async function initData(classIDList) {
 | 
	
		
			
				|  |  | -        if (!classIDList || !classIDList.length) {
 | 
	
		
			
				|  |  | -            return clear();
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | -        $.bootstrapLoading.start();
 | 
	
		
			
				|  |  | -        try {
 | 
	
		
			
				|  |  | -            cache = await ajaxPost('/priceInfo/getPriceData', { classIDList }, TIME_OUT);
 | 
	
		
			
				|  |  | -            cache = _.sortBy(cache, 'classCode');
 | 
	
		
			
				|  |  | -            showData(sheet, cache, setting.header, 5);
 | 
	
		
			
				|  |  | -            const row = sheet.getActiveRowIndex();
 | 
	
		
			
				|  |  | -            const keywordList = cache[row] && cache[row].keywordList || [];
 | 
	
		
			
				|  |  | -            KEYWORD_BOOK.showKeywordData(keywordList);
 | 
	
		
			
				|  |  | -        } catch (err) {
 | 
	
		
			
				|  |  | -            cache = [];
 | 
	
		
			
				|  |  | -            sheet.setRowCount(0);
 | 
	
		
			
				|  |  | -            alert(err);
 | 
	
		
			
				|  |  | -        } finally {
 | 
	
		
			
				|  |  | -            $.bootstrapLoading.end();
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    // 获取当前表中行数据
 | 
	
		
			
				|  |  | -    function getRowData(sheet, row, headers) {
 | 
	
		
			
				|  |  | -        const item = {};
 | 
	
		
			
				|  |  | -        headers.forEach(({ dataCode }, index) => {
 | 
	
		
			
				|  |  | -            const value = sheet.getValue(row, index) || '';
 | 
	
		
			
				|  |  | -            if (value) {
 | 
	
		
			
				|  |  | -                item[dataCode] = value;
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -        });
 | 
	
		
			
				|  |  | -        return item;
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    // 获取表数据和缓存数据的不同数据
 | 
	
		
			
				|  |  | -    function getRowDiffData(curRowData, cacheRowData, headers) {
 | 
	
		
			
				|  |  | -        let item = null;
 | 
	
		
			
				|  |  | -        headers.forEach(({ dataCode }) => {
 | 
	
		
			
				|  |  | -            const curValue = curRowData[dataCode];
 | 
	
		
			
				|  |  | -            const cacheValue = cacheRowData[dataCode];
 | 
	
		
			
				|  |  | -            if (!cacheValue && !curValue) {
 | 
	
		
			
				|  |  | -                return;
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -            if (cacheValue !== curValue) {
 | 
	
		
			
				|  |  | -                if (!item) {
 | 
	
		
			
				|  |  | -                    item = {};
 | 
	
		
			
				|  |  | -                }
 | 
	
		
			
				|  |  | -                item[dataCode] = curValue || '';
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -        });
 | 
	
		
			
				|  |  | -        return item;
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    // 编辑处理
 | 
	
		
			
				|  |  | -    async function handleEdit(changedCells) {
 | 
	
		
			
				|  |  | -        const postData = []; // 请求用
 | 
	
		
			
				|  |  | -        // 更新缓存用
 | 
	
		
			
				|  |  | -        const updateData = [];
 | 
	
		
			
				|  |  | -        const deleteData = [];
 | 
	
		
			
				|  |  | -        const insertData = [];
 | 
	
		
			
				|  |  | -        try {
 | 
	
		
			
				|  |  | -            changedCells.forEach(({ row }) => {
 | 
	
		
			
				|  |  | -                if (cache[row]) {
 | 
	
		
			
				|  |  | -                    const rowData = getRowData(sheet, row, setting.header);
 | 
	
		
			
				|  |  | -                    if (Object.keys(rowData).length) { // 还有数据,更新
 | 
	
		
			
				|  |  | -                        const diffData = getRowDiffData(rowData, cache[row], setting.header);
 | 
	
		
			
				|  |  | -                        if (diffData) {
 | 
	
		
			
				|  |  | -                            postData.push({ type: UpdateType.UPDATE, ID: cache[row].ID, data: diffData });
 | 
	
		
			
				|  |  | -                            updateData.push({ row, data: diffData });
 | 
	
		
			
				|  |  | -                        }
 | 
	
		
			
				|  |  | -                    } else { // 该行无数据了,删除
 | 
	
		
			
				|  |  | -                        postData.push({ type: UpdateType.DELETE, ID: cache[row].ID });
 | 
	
		
			
				|  |  | -                        deleteData.push(cache[row]);
 | 
	
		
			
				|  |  | -                    }
 | 
	
		
			
				|  |  | -                } else { // 新增
 | 
	
		
			
				|  |  | -                    const rowData = getRowData(sheet, row, setting.header);
 | 
	
		
			
				|  |  | -                    if (Object.keys(rowData).length) {
 | 
	
		
			
				|  |  | -                        rowData.ID = uuid.v1();
 | 
	
		
			
				|  |  | -                        rowData.libID = libID;
 | 
	
		
			
				|  |  | -                        rowData.compilationID = compilationID;
 | 
	
		
			
				|  |  | -                        rowData.areaID = AREA_BOOK.curArea.ID;
 | 
	
		
			
				|  |  | -                        rowData.classID = CLASS_BOOK.curClass.ID;
 | 
	
		
			
				|  |  | -                        rowData.period = curLibPeriod;
 | 
	
		
			
				|  |  | -                        postData.push({ type: UpdateType.CREATE, data: rowData });
 | 
	
		
			
				|  |  | -                        insertData.push(rowData);
 | 
	
		
			
				|  |  | -                    }
 | 
	
		
			
				|  |  | -                }
 | 
	
		
			
				|  |  | -            });
 | 
	
		
			
				|  |  | -            if (postData.length) {
 | 
	
		
			
				|  |  | -                await ajaxPost('/priceInfo/editPriceData', { postData }, TIME_OUT);
 | 
	
		
			
				|  |  | -                // 更新缓存,先更新然后删除,最后再新增,防止先新增后缓存数据的下标与更新、删除数据的下标对应不上
 | 
	
		
			
				|  |  | -                updateData.forEach(item => {
 | 
	
		
			
				|  |  | -                    Object.assign(cache[item.row], item.data);
 | 
	
		
			
				|  |  | -                });
 | 
	
		
			
				|  |  | -                deleteData.forEach(item => {
 | 
	
		
			
				|  |  | -                    const index = cache.indexOf(item);
 | 
	
		
			
				|  |  | -                    if (index >= 0) {
 | 
	
		
			
				|  |  | -                        cache.splice(index, 1);
 | 
	
		
			
				|  |  | -                    }
 | 
	
		
			
				|  |  | -                });
 | 
	
		
			
				|  |  | -                insertData.forEach(item => cache.push(item));
 | 
	
		
			
				|  |  | -                if (deleteData.length || insertData.length) {
 | 
	
		
			
				|  |  | -                    showData(sheet, cache, setting.header, 5);
 | 
	
		
			
				|  |  | -                }
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -        } catch (err) {
 | 
	
		
			
				|  |  | -            // 恢复各单元格数据
 | 
	
		
			
				|  |  | -            showData(sheet, cache, setting.header, 5);
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -    sheet.bind(GC.Spread.Sheets.Events.ValueChanged, function (e, info) {
 | 
	
		
			
				|  |  | -        const changedCells = [{ row: info.row }];
 | 
	
		
			
				|  |  | -        handleEdit(changedCells);
 | 
	
		
			
				|  |  | -    });
 | 
	
		
			
				|  |  | -    sheet.bind(GC.Spread.Sheets.Events.SelectionChanged, function (e, info) {
 | 
	
		
			
				|  |  | -        const row = info.newSelections && info.newSelections[0] ? info.newSelections[0].row : 0;
 | 
	
		
			
				|  |  | -        // 显示关键字数据
 | 
	
		
			
				|  |  | -        const keywordList = cache[row] && cache[row].keywordList || [];
 | 
	
		
			
				|  |  | -        KEYWORD_BOOK.showKeywordData(keywordList);
 | 
	
		
			
				|  |  | -    });
 | 
	
		
			
				|  |  | -    sheet.bind(GC.Spread.Sheets.Events.RangeChanged, function (e, info) {
 | 
	
		
			
				|  |  | -        const changedRows = [];
 | 
	
		
			
				|  |  | -        let preRow;
 | 
	
		
			
				|  |  | -        info.changedCells.forEach(({ row }) => {
 | 
	
		
			
				|  |  | -            if (row !== preRow) {
 | 
	
		
			
				|  |  | -                changedRows.push({ row });
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -            preRow = row;
 | 
	
		
			
				|  |  | -        });
 | 
	
		
			
				|  |  | -        handleEdit(changedRows);
 | 
	
		
			
				|  |  | -    });
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    return {
 | 
	
		
			
				|  |  | -        clear,
 | 
	
		
			
				|  |  | -        initData,
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -})();
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |  $(document).ready(() => {
 | 
	
		
			
				|  |  |      console.log('进入信息价');
 | 
	
		
			
				|  |  |      $('[data-toggle="tooltip"]').tooltip();
 | 
	
		
			
				|  |  |      AREA_BOOK.handleSelectionChanged(0);
 | 
	
		
			
				|  |  |      const $range = $(document.body);
 | 
	
		
			
				|  |  |      lockUtil.lockTools($range, locked);
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |  });
 |