|
@@ -0,0 +1,449 @@
|
|
|
+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 initSheet(dom, setting) {
|
|
|
+ const workBook = sheetCommonObj.buildSheet(dom, setting);
|
|
|
+ const sheet = workBook.getSheet(0);
|
|
|
+ setAlign(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 AREA_BOOK = (() => {
|
|
|
+ const cache = areaList;
|
|
|
+ const setting = {
|
|
|
+ header: [{ headerName: '地区', headerWidth: $('#area-spread').width(), dataCode: 'name', dataType: 'String', hAlign: 'center', vAlign: 'center' }]
|
|
|
+ };
|
|
|
+ // 初始化表格
|
|
|
+ const workBook = initSheet($('#area-spread')[0], setting);
|
|
|
+ const sheet = workBook.getSheet(0);
|
|
|
+
|
|
|
+ // 显示数据
|
|
|
+ showData(sheet, cache, setting.header);
|
|
|
+
|
|
|
+ // 编辑处理
|
|
|
+ async function handleEdit(changedCells) {
|
|
|
+ const updateData = [];
|
|
|
+ changedCells.forEach(({ row, col }) => {
|
|
|
+ updateData.push({
|
|
|
+ row,
|
|
|
+ ID: cache[row].ID,
|
|
|
+ name: sheet.getValue(row, col)
|
|
|
+ });
|
|
|
+ });
|
|
|
+ try {
|
|
|
+ await ajaxPost('/priceInfo/editArea', { updateData }, TIME_OUT);
|
|
|
+ updateData.forEach(({ row, name }) => cache[row].name = name);
|
|
|
+ } catch (err) {
|
|
|
+ // 恢复各单元格数据
|
|
|
+ sheetCommonObj.renderSheetFunc(sheet, () => {
|
|
|
+ changedCells.forEach(({ row }) => {
|
|
|
+ sheet.setValue(cache[row].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 curArea = { ID: null };
|
|
|
+ // 焦点变更处理
|
|
|
+ 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, function (e, info) {
|
|
|
+ const row = info.newSelections && info.newSelections[0] ? info.newSelections[0].row : 0;
|
|
|
+ handleSelectionChanged(row);
|
|
|
+ });
|
|
|
+
|
|
|
+ // 新增
|
|
|
+ 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 && typeof target.row !== 'undefined' && typeof target.col !== 'undefined') { // 在表格内
|
|
|
+ const sel = sheet.getSelections()[0];
|
|
|
+ if (sel && sel.rowCount === 1) {
|
|
|
+ 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",
|
|
|
+ callback: function (key, opt) {
|
|
|
+ insert();
|
|
|
+ }
|
|
|
+ },
|
|
|
+ del: {
|
|
|
+ name: '删除',
|
|
|
+ icon: "fa-arrow-left",
|
|
|
+ disabled: function () {
|
|
|
+ return !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);
|
|
|
+ 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);
|
|
|
+ } catch (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,
|
|
|
+ ID: tree.items[row].data.ID,
|
|
|
+ name: sheet.getValue(row, col)
|
|
|
+ });
|
|
|
+ });
|
|
|
+ try {
|
|
|
+ await ajaxPost('/priceInfo/editClassData', { updateData }, TIME_OUT);
|
|
|
+ updateData.forEach(({ row, 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 curClass = { ID: null };
|
|
|
+ function handleSelectionChanged(row) {
|
|
|
+ const classNode = tree.items[row];
|
|
|
+ curClass.ID = classNode && classNode.data && classNode.data.ID || null;
|
|
|
+ PRICE_BOOK.initData(curClass.ID);
|
|
|
+ }
|
|
|
+ sheet.bind(GC.Spread.Sheets.Events.SelectionChanged, function (e, info) {
|
|
|
+ const row = info.newSelections && info.newSelections[0] ? info.newSelections[0].row : 0;
|
|
|
+ handleSelectionChanged(row);
|
|
|
+ });
|
|
|
+
|
|
|
+ return {
|
|
|
+ initData,
|
|
|
+ handleSelectionChanged,
|
|
|
+ curClass,
|
|
|
+ }
|
|
|
+
|
|
|
+})();
|
|
|
+
|
|
|
+// 价格信息表
|
|
|
+const PRICE_BOOK = (() => {
|
|
|
+ const setting = {
|
|
|
+ header: [
|
|
|
+ { headerName: '编码', headerWidth: 100, dataCode: 'code', dataType: 'String', hAlign: 'left', vAlign: 'center' },
|
|
|
+ { 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' },
|
|
|
+ ],
|
|
|
+ };
|
|
|
+ // 初始化表格
|
|
|
+ const workBook = initSheet($('#price-spread')[0], setting);
|
|
|
+ const sheet = workBook.getSheet(0);
|
|
|
+
|
|
|
+ let cache = [];
|
|
|
+ // 清空
|
|
|
+ function clear() {
|
|
|
+ cache = [];
|
|
|
+ sheet.setRowCount(0);
|
|
|
+ }
|
|
|
+ // 初始化数据
|
|
|
+ async function initData(classID) {
|
|
|
+ if (!classID) {
|
|
|
+ return clear();
|
|
|
+ }
|
|
|
+ $.bootstrapLoading.start();
|
|
|
+ try {
|
|
|
+ cache = await ajaxPost('/priceInfo/getPriceData', { classID }, TIME_OUT);
|
|
|
+ showData(sheet, cache, setting.header, 5);
|
|
|
+ } 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: 'update', ID: cache[row].ID, data: diffData });
|
|
|
+ updateData.push({ row, data: diffData });
|
|
|
+ }
|
|
|
+ } else { // 该行无数据了,删除
|
|
|
+ postData.push({ type: '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.areaID = AREA_BOOK.curArea.ID;
|
|
|
+ rowData.classID = CLASS_BOOK.curClass.ID;
|
|
|
+ postData.push({ type: '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.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(() => {
|
|
|
+ AREA_BOOK.handleSelectionChanged(0);
|
|
|
+});
|