| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530 | // 分类表function setTimeoutSync(handle, time) {  return new Promise(function (resolve, reject) {    setTimeout(function () {      if (handle && typeof handle === 'function') {        handle();      }      resolve();    }, time);  });}// 分类表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) {      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');  const $matchSummary = $('#match-summary');  const $batchMatchSummary = $('#batch-match-summary');  const $showEmpty = $('#show-empty');  // 插入  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) {      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) {    curRow = 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);  const reload = () => {    if (curClass.ID) {      const node = tree.nodes[tree.prefix + curClass.ID];      if (node) {        handleSelectionChanged(node.serialNo())      }    }  }  $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 }));  const doMatchSummary = async (libID, compilationID, areaID) => {    await ajaxPost('/priceInfo/matchSummary', { libID, compilationID, areaID }, 1000 * 60 * 10);  }  // 匹配总表  $matchSummary.click(_.debounce(async () => {    $.bootstrapLoading.progressStart('匹配总表', true);    $("#progress_modal_body").text('正在匹配总表,请稍后...');    try {      const matchAll = $('#match-all-input')[0].checked;      const areaID = matchAll ? '' : AREA_BOOK.curArea?.ID;      await doMatchSummary(libID, compilationID, areaID);      setTimeout(() => {        $.bootstrapLoading.progressEnd();        window.location.reload()      }, 1000)    } catch (error) {      alert(error)      console.log(error);      $.bootstrapLoading.progressEnd();    }  }, DEBOUNCE_TIME, { leading: true }));  // 批量匹配总表  $batchMatchSummary.click(_.debounce(async () => {    $.bootstrapLoading.progressStart('批量匹配总表', true);    try {      const libs = await ajaxPost('/priceInfo/getAllLibs');      for (const lib of libs) {        $("#progress_modal_body").text(`${lib.name},正在匹配总表,请稍后(${libs.indexOf(lib) + 1}/${libs.length})...`);        await doMatchSummary(lib.ID, lib.compilationID, '');        await setTimeoutSync(() => { }, 100);      }      await setTimeoutSync(() => {        $.bootstrapLoading.progressEnd();        window.location.reload()      }, 1000);    } catch (error) {      alert(error)      console.log(error);      $.bootstrapLoading.progressEnd();    }  }, DEBOUNCE_TIME, { leading: true }));  // 显示空数据  $showEmpty.click(() => {    $('#empty-area').modal('show');  });  return {    initData,    handleSelectionChanged,    curClass,    reload,  }})();
 |