priceClass.js 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471
  1. // 分类表
  2. const CLASS_BOOK = (() => {
  3. const setting = {
  4. header: [{ headerName: '分类', headerWidth: $('#area-spread').width(), dataCode: 'name', dataType: 'String', hAlign: 'left', vAlign: 'center' }],
  5. controller: {
  6. cols: [
  7. {
  8. data: {
  9. field: 'name',
  10. vAlign: 1,
  11. hAlign: 0,
  12. font: 'Arial'
  13. },
  14. }
  15. ],
  16. headRows: 1,
  17. headRowHeight: [30],
  18. emptyRows: 0,
  19. treeCol: 0
  20. },
  21. tree: {
  22. id: 'ID',
  23. pid: 'ParentID',
  24. nid: 'NextSiblingID',
  25. rootId: -1
  26. }
  27. };
  28. // 初始化表格
  29. const workBook = initSheet($('#class-spread')[0], setting);
  30. workBook.options.allowExtendPasteRange = false;
  31. workBook.options.allowUserDragDrop = true;
  32. workBook.options.allowUserDragFill = true;
  33. const sheet = workBook.getSheet(0);
  34. let tree;
  35. let controller;
  36. // 初始化数据
  37. async function initData(libID, areaID) {
  38. if (!areaID) {
  39. tree = null;
  40. controller = null;
  41. sheet.setRowCount(0);
  42. PRICE_BOOK.clear();
  43. return;
  44. }
  45. $.bootstrapLoading.start();
  46. try {
  47. const data = await ajaxPost('/priceInfo/getClassData', { libID, areaID }, TIME_OUT);
  48. tree = idTree.createNew(setting.tree);
  49. tree.loadDatas(data);
  50. tree.selected = tree.items.length > 0 ? tree.items[0] : null;
  51. controller = TREE_SHEET_CONTROLLER.createNew(tree, sheet, setting.controller, false);
  52. controller.showTreeData();
  53. handleSelectionChanged(0);
  54. sheet.setSelection(0, 0, 1, 1);
  55. lockUtil.lockSpreads([workBook], locked);
  56. } catch (err) {
  57. tree = null;
  58. controller = null;
  59. sheet.setRowCount(0);
  60. alert(err);
  61. } finally {
  62. $.bootstrapLoading.end();
  63. }
  64. }
  65. // 编辑处理
  66. async function handleEdit(changedCells) {
  67. const updateData = [];
  68. changedCells.forEach(({ row, col }) => {
  69. updateData.push({
  70. row,
  71. type: UpdateType.UPDATE,
  72. filter: { ID: tree.items[row].data.ID },
  73. update: { name: sheet.getValue(row, col) }
  74. });
  75. });
  76. try {
  77. await ajaxPost('/priceInfo/editClassData', { updateData }, TIME_OUT);
  78. updateData.forEach(({ row, update: { name } }) => tree.items[row].data.name = name);
  79. } catch (err) {
  80. // 恢复各单元格数据
  81. sheetCommonObj.renderSheetFunc(sheet, () => {
  82. changedCells.forEach(({ row }) => {
  83. sheet.setValue(tree.items[row].data.name);
  84. });
  85. });
  86. }
  87. }
  88. sheet.bind(GC.Spread.Sheets.Events.ValueChanged, function (e, info) {
  89. const changedCells = [{ row: info.row, col: info.col }];
  90. handleEdit(changedCells);
  91. });
  92. sheet.bind(GC.Spread.Sheets.Events.RangeChanged, function (e, info) {
  93. handleEdit(info.changedCells);
  94. });
  95. // 树操作相关
  96. const $insert = $('#tree-insert');
  97. const $remove = $('#tree-remove');
  98. const $upLevel = $('#tree-up-level');
  99. const $downLevel = $('#tree-down-level');
  100. const $downMove = $('#tree-down-move');
  101. const $upMove = $('#tree-up-move');
  102. const $calcPriceIndex = $('#calc-price-index');
  103. const $matchSummary = $('#match-summary');
  104. // 插入
  105. let canInsert = true;
  106. async function insert() {
  107. try {
  108. if (!canInsert) {
  109. return false;
  110. }
  111. canInsert = false;
  112. $.bootstrapLoading.start();
  113. const updateData = [];
  114. const selected = tree.selected;
  115. const newItem = {
  116. libID,
  117. areaID: AREA_BOOK.curArea.ID,
  118. ID: uuid.v1(),
  119. name: '',
  120. ParentID: '-1',
  121. NextSiblingID: '-1'
  122. };
  123. if (selected) {
  124. newItem.ParentID = selected.data.ParentID;
  125. updateData.push({
  126. type: UpdateType.UPDATE,
  127. filter: { ID: selected.data.ID },
  128. update: { NextSiblingID: newItem.ID }
  129. });
  130. if (selected.nextSibling) {
  131. newItem.NextSiblingID = selected.nextSibling.data.ID;
  132. }
  133. }
  134. updateData.push({
  135. type: UpdateType.CREATE,
  136. document: newItem
  137. });
  138. await ajaxPost('/priceInfo/editClassData', { updateData });
  139. controller.insertByID(newItem.ID);
  140. handleSelectionChanged(sheet.getActiveRowIndex());
  141. } catch (err) {
  142. alert(err);
  143. } finally {
  144. canInsert = true;
  145. $.bootstrapLoading.end();
  146. }
  147. }
  148. $insert.click(_.debounce(insert, DEBOUNCE_TIME, { leading: true }));
  149. // 删除
  150. let canRemove = true;
  151. async function remove() {
  152. try {
  153. if (!canRemove) {
  154. return false;
  155. }
  156. canRemove = false;
  157. $.bootstrapLoading.start();
  158. const updateData = [];
  159. const selected = tree.selected;
  160. const children = selected.getPosterity();
  161. [selected, ...children].forEach(node => updateData.push({
  162. type: UpdateType.DELETE,
  163. filter: { ID: node.data.ID }
  164. }));
  165. if (selected.preSibling) {
  166. updateData.push({
  167. type: UpdateType.UPDATE,
  168. filter: { ID: selected.preSibling.data.ID },
  169. update: { NextSiblingID: selected.data.NextSiblingID }
  170. });
  171. }
  172. await ajaxPost('/priceInfo/editClassData', { updateData });
  173. controller.delete();
  174. handleSelectionChanged(sheet.getActiveRowIndex());
  175. } catch (err) {
  176. alert(err);
  177. } finally {
  178. canRemove = true;
  179. $.bootstrapLoading.end();
  180. }
  181. }
  182. $remove.click(_.debounce(remove, DEBOUNCE_TIME, { leading: true }));
  183. // 升级
  184. let canUpLevel = true;
  185. async function upLevel() {
  186. try {
  187. if (!canUpLevel) {
  188. return false;
  189. }
  190. canUpLevel = false;
  191. $.bootstrapLoading.start();
  192. const updateData = [];
  193. const selected = tree.selected;
  194. if (selected.preSibling) {
  195. updateData.push({
  196. type: UpdateType.UPDATE,
  197. filter: { ID: selected.preSibling.data.ID },
  198. update: { NextSiblingID: -1 }
  199. });
  200. }
  201. if (selected.parent) {
  202. updateData.push({
  203. type: UpdateType.UPDATE,
  204. filter: { ID: selected.parent.data.ID },
  205. update: { NextSiblingID: selected.data.ID }
  206. });
  207. }
  208. updateData.push({
  209. type: UpdateType.UPDATE,
  210. filter: { ID: selected.data.ID },
  211. update: { ParentID: selected.parent.data.ParentID, NextSiblingID: selected.parent.data.NextSiblingID }
  212. });
  213. let curNode = selected.nextSibling;
  214. while (curNode) {
  215. updateData.push({
  216. type: UpdateType.UPDATE,
  217. filter: { ID: curNode.data.ID },
  218. update: { ParentID: selected.data.ID }
  219. });
  220. curNode = curNode.nextSibling;
  221. }
  222. await ajaxPost('/priceInfo/editClassData', { updateData });
  223. controller.upLevel();
  224. refreshTreeButton(tree.selected);
  225. } catch (err) {
  226. alert(err);
  227. } finally {
  228. canUpLevel = true;
  229. $.bootstrapLoading.end();
  230. }
  231. }
  232. $upLevel.click(_.debounce(upLevel, DEBOUNCE_TIME, { leading: true }));
  233. // 降级
  234. let canDownLevel = true;
  235. async function downLevel() {
  236. try {
  237. if (!canDownLevel) {
  238. return false;
  239. }
  240. canDownLevel = false;
  241. $.bootstrapLoading.start();
  242. const updateData = [];
  243. const selected = tree.selected;
  244. if (selected.preSibling) {
  245. updateData.push({
  246. type: UpdateType.UPDATE,
  247. filter: { ID: selected.preSibling.data.ID },
  248. update: { NextSiblingID: selected.data.NextSiblingID }
  249. });
  250. const preSiblingLastChild = selected.preSibling.children[selected.preSibling.children.length - 1];
  251. if (preSiblingLastChild) {
  252. updateData.push({
  253. type: UpdateType.UPDATE,
  254. filter: { ID: preSiblingLastChild.data.ID },
  255. update: { NextSiblingID: selected.data.ID }
  256. });
  257. }
  258. updateData.push({
  259. type: UpdateType.UPDATE,
  260. filter: { ID: selected.data.ID },
  261. update: { ParentID: selected.preSibling.data.ID, NextSiblingID: -1 }
  262. });
  263. }
  264. await ajaxPost('/priceInfo/editClassData', { updateData });
  265. controller.downLevel();
  266. refreshTreeButton(tree.selected);
  267. } catch (err) {
  268. alert(err);
  269. } finally {
  270. canDownLevel = true;
  271. $.bootstrapLoading.end();
  272. }
  273. }
  274. $downLevel.click(_.debounce(downLevel, DEBOUNCE_TIME, { leading: true }));
  275. // 下移
  276. let canDownMove = true;
  277. async function downMove() {
  278. try {
  279. if (!canDownMove) {
  280. return false;
  281. }
  282. canDownMove = false;
  283. $.bootstrapLoading.start();
  284. const updateData = [];
  285. const selected = tree.selected;
  286. if (selected.preSibling) {
  287. updateData.push({
  288. type: UpdateType.UPDATE,
  289. filter: { ID: selected.preSibling.data.ID },
  290. update: { NextSiblingID: selected.data.NextSiblingID }
  291. });
  292. }
  293. updateData.push({
  294. type: UpdateType.UPDATE,
  295. filter: { ID: selected.data.ID },
  296. update: { NextSiblingID: selected.nextSibling.data.NextSiblingID }
  297. });
  298. updateData.push({
  299. type: UpdateType.UPDATE,
  300. filter: { ID: selected.nextSibling.data.ID },
  301. update: { NextSiblingID: selected.data.ID }
  302. });
  303. await ajaxPost('/priceInfo/editClassData', { updateData });
  304. controller.downMove();
  305. refreshTreeButton(tree.selected);
  306. } catch (err) {
  307. alert(err);
  308. } finally {
  309. canDownMove = true;
  310. $.bootstrapLoading.end();
  311. }
  312. }
  313. $downMove.click(_.debounce(downMove, DEBOUNCE_TIME, { leading: true }));
  314. // 上移
  315. let canUpMove = true;
  316. async function upMove() {
  317. try {
  318. if (!canUpMove) {
  319. return false;
  320. }
  321. canUpMove = false;
  322. $.bootstrapLoading.start();
  323. const updateData = [];
  324. const selected = tree.selected;
  325. if (selected.preSibling) {
  326. updateData.push({
  327. type: UpdateType.UPDATE,
  328. filter: { ID: selected.preSibling.data.ID },
  329. update: { NextSiblingID: selected.data.NextSiblingID }
  330. });
  331. }
  332. const prePreSibling = selected.preSibling.preSibling;
  333. if (prePreSibling) {
  334. updateData.push({
  335. type: UpdateType.UPDATE,
  336. filter: { ID: prePreSibling.data.ID },
  337. update: { NextSiblingID: selected.data.ID }
  338. });
  339. }
  340. updateData.push({
  341. type: UpdateType.UPDATE,
  342. filter: { ID: selected.data.ID },
  343. update: { NextSiblingID: selected.preSibling.data.ID }
  344. });
  345. await ajaxPost('/priceInfo/editClassData', { updateData });
  346. controller.upMove();
  347. refreshTreeButton(tree.selected);
  348. } catch (err) {
  349. alert(err);
  350. } finally {
  351. canUpMove = true;
  352. $.bootstrapLoading.end();
  353. }
  354. }
  355. $upMove.click(_.debounce(upMove, DEBOUNCE_TIME, { leading: true }));
  356. // 刷新树操作按钮有效性
  357. function refreshTreeButton(selected) {
  358. if (locked) {
  359. return;
  360. }
  361. $insert.removeClass('disabled');
  362. $remove.removeClass('disabled');
  363. $upLevel.removeClass('disabled');
  364. $downLevel.removeClass('disabled');
  365. $downMove.removeClass('disabled');
  366. $upMove.removeClass('disabled');
  367. if (!selected) {
  368. $remove.addClass('disabled');
  369. $upLevel.addClass('disabled');
  370. $downLevel.addClass('disabled');
  371. $downMove.addClass('disabled');
  372. $upMove.addClass('disabled');
  373. } else {
  374. if (!selected.preSibling) {
  375. $downLevel.addClass('disabled');
  376. $upMove.addClass('disabled');
  377. }
  378. if (!selected.nextSibling) {
  379. $downMove.addClass('disabled');
  380. }
  381. if (!selected.parent) {
  382. $upLevel.addClass('disabled');
  383. }
  384. }
  385. }
  386. // 焦点变更处理
  387. const curClass = { ID: null };
  388. function handleSelectionChanged(row) {
  389. const classNode = tree.items[row] || null;
  390. tree.selected = classNode;
  391. refreshTreeButton(classNode);
  392. curClass.ID = classNode && classNode.data && classNode.data.ID || null;
  393. const classIDList = []
  394. if (classNode) {
  395. classIDList.push(classNode.data.ID);
  396. const children = classNode.getPosterity();
  397. children.forEach(child => classIDList.push(child.data.ID));
  398. }
  399. PRICE_BOOK.initData(classIDList);
  400. }
  401. const debounceSelectionChanged = _.debounce(function (e, info) {
  402. const row = info.newSelections && info.newSelections[0] ? info.newSelections[0].row : 0;
  403. handleSelectionChanged(row);
  404. }, DEBOUNCE_TIME, { leading: true });
  405. sheet.bind(GC.Spread.Sheets.Events.SelectionChanged, debounceSelectionChanged);
  406. $calcPriceIndex.click(_.debounce(async () => {
  407. $.bootstrapLoading.start();
  408. try {
  409. const data = await ajaxPost('/priceInfo/calcPriceIndex', { libID, period: curLibPeriod, compilationID }, TIME_OUT);
  410. //alert(data);
  411. if (data) {
  412. const htmlStr = data.replace(/\n/gm, '<br>'); //replaceAll('\n','<br>',data);
  413. $("#result-info-body").html(htmlStr);
  414. $("#result-info").modal('show');
  415. } else {
  416. alert('计算完成!')
  417. }
  418. } catch (error) {
  419. console.log(error);
  420. }
  421. $.bootstrapLoading.end();
  422. }, DEBOUNCE_TIME, { leading: true }));
  423. // 匹配总表
  424. $matchSummary.click(_.debounce(async () => {
  425. $.bootstrapLoading.progressStart('匹配总表', true);
  426. $("#progress_modal_body").text('正在匹配总表,请稍后...');
  427. try {
  428. await ajaxPost('/priceInfo/matchSummary', { libID, compilationID }, 1000 * 60 * 10);
  429. $.bootstrapLoading.progressEnd();
  430. window.location.reload()
  431. } catch (error) {
  432. alert(error)
  433. console.log(error);
  434. $.bootstrapLoading.progressEnd();
  435. }
  436. }, DEBOUNCE_TIME, { leading: true }))
  437. return {
  438. initData,
  439. handleSelectionChanged,
  440. curClass,
  441. }
  442. })();