| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317 | // 空数据表const EMPTY_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: 100, dataCode: 'expString', dataType: 'String', hAlign: 'left', vAlign: 'center' },      { headerName: '材料名称', headerWidth: 275, dataCode: 'name', dataType: 'String', hAlign: 'left', vAlign: 'center' },      { headerName: '规格型号', headerWidth: 180, dataCode: 'specs', dataType: 'String', hAlign: 'left', vAlign: 'center' },      { headerName: '单位', headerWidth: 80, dataCode: 'unit', dataType: 'String', hAlign: 'center', vAlign: 'center' },    ],  };  // 初始化表格  const workBookObj = {    book: null,    sheet: null,  };  const buildWorkBook = () => {    workBookObj.book = initSheet($('.empty-spread')[0], setting);    workBookObj.book.options.allowUserDragDrop = true;    workBookObj.book.options.allowUserDragFill = true;    workBookObj.book.options.allowExtendPasteRange = false;    lockUtil.lockSpreads([workBookObj.book], locked);    workBookObj.sheet = workBookObj.book.getSheet(0);  }  // 总数据(数据没合并前)  let totalData = [];  let totalMap = {};  // 表格显示的数据(合并后)  const cache = [];  const getCompareKey = (item) => {    const props = ['name', 'specs', 'unit'];    return props.map(prop => item[prop] ? item[prop].trim() : '').join('@');  }  const setTotalMap = (items) => {    totalMap = {};    items.forEach(item => {      const key = getCompareKey(item);      if (totalMap[key]) {        totalMap[key].push(item);      } else {        totalMap[key] = [item];      }    })  }  // 获取表格数据,汇总空数据,多地区可能存在相同材料,按名称规格单位做筛选,重复材料仅显示一条即可  const getTableData = (items) => {    const map = {};    items.forEach(item => {      const key = getCompareKey(item);      if (!map[key]) {        map[key] = { ...item };      }    });    return Object.values(map);  }  // 根据表格数据,获取实际信息价数据(一对多)  const getItemsFromTableItem = (item) => {    const key = getCompareKey(item);    return totalMap[key] || [];  }  // 获取材料关键字: 名称 规格  const getKeyword = (item) => {    return item ? `${item.name} ${item.specs}` : '';  }  // 改变关键字  const changeKeyword = (item) => {    const keyword = getKeyword(item);    $('#recommend-search').val(keyword);    if (!keyword) {      RECOMMEND_BOOK.clear();    } else {      RECOMMEND_BOOK.loadRecommendData(keyword);    }  }  // 清空  function clear() {    cache.length = 0;    workBookObj.sheet.setRowCount(0);  }  let curRow = 0;  // 初始化数据  async function initData() {    clear();    curRow = 0;    $.bootstrapLoading.start();    try {      const matchAll = $('#match-all-input')[0].checked;      const areaID = matchAll ? '' : AREA_BOOK.curArea?.ID;      totalData = await ajaxPost('/priceInfo/getPriceEmptyData', { libID, compilationID, areaID }, 1000 * 60 * 10);      setTotalMap(totalData);      const tableData = getTableData(totalData);      cache.push(...tableData)      showData(workBookObj.sheet, cache, setting.header);      changeKeyword(cache[0]);    } catch (err) {      clear();      alert(err);    } finally {      $.bootstrapLoading.end();    }  }  // 编辑处理  async function handleEdit(changedCells, diffMap, needRefresh) {    const postData = []; // 请求用    // 更新缓存用    const updateData = [];    const deleteData = [];    const insertData = [];    try {      changedCells.forEach(({ row }) => {        if (cache[row]) {          const rowData = getRowData(workBookObj.sheet, row, setting.header);          if (Object.keys(rowData).length) { // 还有数据,更新            let diffData;            if (diffMap) {              diffData = diffMap[row];            } else {              diffData = getRowDiffData(rowData, cache[row], setting.header);            }            if (diffData) {              // 改一行, 实际可能是改多行,表格一行数据是多行合并显示的              const items = getItemsFromTableItem(cache[row]);              items.forEach(item => {                // 只有珠海建筑才更新计算式                const updateObj = { ...diffData };                const area = AREA_BOOK.cache.find(areaItem => areaItem.ID === item.areaID);                if (diffMap) {                  delete updateObj.expString;                  delete diffData.expString;                }                postData.push({ type: UpdateType.UPDATE, ID: item.ID, areaID: area.ID, compilationID, period: curLibPeriod, data: updateObj });              });              updateData.push({ row, data: diffData });            }          } else { // 该行无数据了,删除            const items = getItemsFromTableItem(cache[row]);            items.forEach(item => {              const area = AREA_BOOK.cache.find(areaItem => areaItem.ID === item.areaID);              postData.push({ type: UpdateType.DELETE, areaID: area.ID, compilationID, period: curLibPeriod, ID: item.ID });            });            deleteData.push(cache[row]);          }        }      });      if (postData.length) {        $.bootstrapLoading.start();        await ajaxPost('/priceInfo/editPriceData', { postData }, TIME_OUT);        // 更新缓存,先更新然后删除,最后再新增,防止先新增后缓存数据的下标与更新、删除数据的下标对应不上        updateData.forEach(item => {          // 更新总表          const curItem = cache[item.row];          const compareKey = getCompareKey(curItem);          const totalItems = totalMap[compareKey];          if (totalItems) {            const newCompareKey = getCompareKey({ ...curItem, ...item.data });            totalItems.forEach(totalItem => {              Object.assign(totalItem, item.data);            });            if (newCompareKey !== compareKey) {              totalMap[newCompareKey] = totalItems;              delete totalMap[compareKey];            }          }          // 更新表格缓存          Object.assign(cache[item.row], item.data);        });        deleteData.forEach(item => {          // 更新总表          const compareKey = getCompareKey(item);          const totalItems = totalMap[compareKey];          if (totalItems) {            const totalItemIDs = totalItems.map(item => item.ID);            totalData = totalData.filter(totalItem => !totalItemIDs.includes(totalItem));            delete totalMap[compareKey];          }          // 更新表格缓存          const index = cache.indexOf(item);          if (index >= 0) {            cache.splice(index, 1);          }        });        insertData.forEach(item => cache.push(item));        if (deleteData.length || insertData.length || needRefresh) {          showData(workBookObj.sheet, cache, setting.header);        }        $.bootstrapLoading.end();        CLASS_BOOK.reload();      }    } catch (err) {      // 恢复各单元格数据      showData(workBookObj.sheet, cache, setting.header);      $.bootstrapLoading.end();    }  }  // 跟新行的编号、编码编码  async function updateRowCode(code, classCode, expString) {    const item = cache[curRow];    if (!item) {      return;    }    const diffData = { code, classCode, expString };    await handleEdit([{ row: curRow }], { [curRow]: diffData }, true);  }  const bindEvent = () => {    workBookObj.sheet.bind(GC.Spread.Sheets.Events.ValueChanged, function (e, info) {      const changedCells = [{ row: info.row }];      handleEdit(changedCells);    });    workBookObj.sheet.bind(GC.Spread.Sheets.Events.SelectionChanged, function (e, info) {      const row = info.newSelections && info.newSelections[0] ? info.newSelections[0].row : 0;      if (curRow !== row) {        const item = cache[row];        changeKeyword(item);      }      curRow = row;    });    workBookObj.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);    });  }  // 将空表的表格保存至总表  const saveInSummary = async () => {    const documents = [];    const removeIDs = [];    cache.filter(item => item.code && item.classCode).forEach(item => {      removeIDs.push(item.ID);      documents.push({        ID: uuid.v1(),        code: item.code,        classCode: item.classCode,        expString: item.expString,        name: item.name,        specs: item.specs,        unit: item.unit,      });    });    if (!documents.length) {      alert('不存在可保存数据');      return;    }    console.log(documents);    try {      $.bootstrapLoading.progressStart('保存至总表', true);      $("#progress_modal_body").text('正在保存至总表,请稍后...');      await ajaxPost('/priceInfoSummary/saveInSummary', { documents }, 1000 * 60 * 5);      setTimeout(() => {        $.bootstrapLoading.progressEnd();        alert('保存成功');        const filterCache = cache.filter(item => !removeIDs.includes(item.ID));        cache.length = 0;        cache.push(...filterCache);        showData(workBookObj.sheet, cache, setting.header);      }, 1000);    } catch (error) {      setTimeout(() => {        $.bootstrapLoading.progressEnd();      }, 500);      console.log(error);      alert(error);    }  }  return {    buildWorkBook,    bindEvent,    clear,    initData,    workBookObj,    updateRowCode,    saveInSummary,  }})();$(document).ready(() => {  $('#empty-area').on('shown.bs.modal', function () {    if (!EMPTY_BOOK.workBookObj.book) {      EMPTY_BOOK.buildWorkBook();      EMPTY_BOOK.bindEvent();    }    EMPTY_BOOK.initData();  });  $('#empty-area').on('hidden.bs.modal', function () {    EMPTY_BOOK.clear();  });  // 保存至总表  $('#save-in-summary').click(() => {    EMPTY_BOOK.saveInSummary();  });});
 |