std_billsGuidance_lib.js 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847
  1. 'use strict';
  2. /**
  3. *
  4. *
  5. * @author Zhong
  6. * @date 2018/6/11
  7. * @version
  8. */
  9. //清单指引/精灵获取完清单数据后的回调函数
  10. let doAfterLoadGuidance = null;
  11. const billsGuidance = (function () {
  12. let currentLib = null;
  13. //库类型
  14. const libType = {'guidance': 1, 'elf': 2}; //清单指引、清单精灵
  15. const libSel = $('#stdBillsGuidanceLibSelect');
  16. //工作内容
  17. let stdBillsJobData = [];
  18. //项目特征
  19. let stdBillsFeatureData = [];
  20. const bills = {
  21. dom: $('#billsGuidance_bills'),
  22. workBook: null,
  23. cache: [],
  24. tree: null,
  25. controller: null,
  26. treeSetting: {
  27. emptyRowHeader: true,
  28. rowHeaderWidth: 15,
  29. treeCol: 0,
  30. emptyRows: 0,
  31. headRows: 1,
  32. headRowHeight: [40],
  33. defaultRowHeight: 21,
  34. cols: [{
  35. width: 140,
  36. readOnly: true,
  37. showHint: true,
  38. head: {
  39. titleNames: ["项目编码"],
  40. spanCols: [1],
  41. spanRows: [1],
  42. vAlign: [1],
  43. hAlign: [1],
  44. font: ["Arial"]
  45. },
  46. data: {
  47. field: "code",
  48. vAlign: 1,
  49. hAlign: 0,
  50. font: "Arial"
  51. }
  52. }, {
  53. width: 190,
  54. readOnly: true,
  55. head: {
  56. titleNames: ["项目名称"],
  57. spanCols: [1],
  58. spanRows: [1],
  59. vAlign: [1],
  60. hAlign: [1],
  61. font: ["Arial"]
  62. },
  63. data: {
  64. field: "name",
  65. vAlign: 1,
  66. hAlign: 0,
  67. font: "Arial"
  68. }
  69. },
  70. {
  71. width: 45,
  72. readOnly: true,
  73. head: {
  74. titleNames: ["计量单位"],
  75. spanCols: [1],
  76. spanRows: [1],
  77. vAlign: [1],
  78. hAlign: [1],
  79. font: ["Arial"]
  80. },
  81. data: {
  82. field: "unit",
  83. vAlign: 1,
  84. hAlign: 1,
  85. font: "Arial"
  86. }
  87. }
  88. ]
  89. },
  90. headers: [
  91. {name: '项目编码', dataCode: 'code', width: 140, vAlign: 'center', hAlign: 'left', formatter: '@'},
  92. {name: '项目名称', dataCode: 'name', width: 190, vAlign: 'center', hAlign: 'left', formatter: '@'},
  93. {name: '单位', dataCode: 'unit', width: 45, vAlign: 'center', hAlign: 'center', formatter: '@'},
  94. ],
  95. rowHeaderWidth:25,
  96. events: {
  97. CellDoubleClick: function (sender, args) {
  98. if(!bills.tree){
  99. return;
  100. }
  101. let node = bills.tree.items[args.row];
  102. if(!node){
  103. return;
  104. }
  105. if(node.children.length === 0){
  106. billsLibObj.insertBills(stdBillsJobData, stdBillsFeatureData, node);
  107. }
  108. else {
  109. node.setExpanded(!node.expanded);
  110. //设置展开收起状态
  111. sessionStorage.setItem('stdBillsGuidanceExpState', bills.tree.getExpState(bills.tree.items));
  112. renderSheetFunc(args.sheet, function () {
  113. let iCount = node.posterityCount(), i, child;
  114. for (i = 0; i < iCount; i++) {
  115. child = bills.tree.items[args.row + i + 1];
  116. args.sheet.setRowVisible(args.row + i + 1, child.visible, args.sheetArea);
  117. }
  118. args.sheet.invalidateLayout();
  119. });
  120. args.sheet.repaint();
  121. }
  122. }
  123. }
  124. };
  125. //项目指引类型
  126. const itemType = {
  127. job: 0,
  128. ration: 1
  129. };
  130. const guideItem = {
  131. dom: $('#billsGuidance_items'),
  132. workBook: null,
  133. tree: null,
  134. controller: null,
  135. treeSetting: {
  136. treeCol: 1,
  137. emptyRows: 0,
  138. headRows: 1,
  139. headRowHeight: [40],
  140. defaultRowHeight: 21,
  141. cols: [
  142. {
  143. width: 35,
  144. readOnly: false,
  145. head: {
  146. titleNames: ["选择"],
  147. spanCols: [1],
  148. spanRows: [1],
  149. vAlign: [1],
  150. hAlign: [1],
  151. font: ["Arial"]
  152. },
  153. data: {
  154. field: "select",
  155. vAlign: 1,
  156. hAlign: 1,
  157. font: "Arial"
  158. }
  159. },
  160. {
  161. width: 420,
  162. readOnly: false,
  163. head: {
  164. titleNames: ["项目指引"],
  165. spanCols: [1],
  166. spanRows: [1],
  167. vAlign: [1],
  168. hAlign: [1],
  169. font: ["Arial"]
  170. },
  171. data: {
  172. field: "name",
  173. vAlign: 1,
  174. hAlign: 0,
  175. font: "Arial"
  176. }
  177. }
  178. ]
  179. },
  180. headers: [
  181. {name: '选择', dataCode: 'select', width: 35, vAlign: 'center', hAlign: 'center', formatter: '@'},
  182. {name: '项目指引', dataCode: 'name', width: 300, vAlign: 'center', hAlign: 'left', formatter: '@'},
  183. ],
  184. rowHeaderWidth:25,
  185. events: {
  186. EditStarting: function (sender, args) {
  187. if(!bills.tree || guideItem.headers[args.col]['dataCode'] === 'name'){
  188. args.cancel = true;
  189. }
  190. },
  191. ButtonClicked: function (sender, args) {
  192. if(args.sheet.isEditing()){
  193. args.sheet.endEdit(true);
  194. }
  195. refreshInsertRation();
  196. },
  197. CellDoubleClick: function (sender, args) {
  198. if(!bills.tree || !bills.tree.selected){
  199. return;
  200. }
  201. let node = bills.tree.selected.guidance.tree.selected;
  202. if(!node){
  203. return;
  204. }
  205. if(node.children.length === 0){
  206. if(guideItem.headers[args.col]['dataCode'] === 'name'){
  207. insertRations(getInsertRationData([args.row]));
  208. }
  209. }
  210. else {
  211. node.setExpanded(!node.expanded);
  212. renderSheetFunc(args.sheet, function () {
  213. let iCount = node.posterityCount(), i, child;
  214. for (i = 0; i < iCount; i++) {
  215. child = bills.tree.selected.guidance.tree.items[args.row + i + 1];
  216. args.sheet.setRowVisible(args.row + i + 1, child.visible, args.sheetArea);
  217. }
  218. args.sheet.invalidateLayout();
  219. });
  220. args.sheet.repaint();
  221. }
  222. }
  223. }
  224. };
  225. const elfItem = {
  226. dom: $('#billsGuidance_items'),
  227. workBook: null,
  228. tree: null,
  229. controller: null,
  230. treeSetting: {
  231. treeCol: 0,
  232. emptyRows: 0,
  233. headRows: 1,
  234. headRowHeight: [40],
  235. defaultRowHeight: 21,
  236. cols: [
  237. {
  238. width: 250,
  239. readOnly: true,
  240. head: {
  241. titleNames: ["施工工序"],
  242. spanCols: [1],
  243. spanRows: [1],
  244. vAlign: [1],
  245. hAlign: [1],
  246. font: ["Arial"]
  247. },
  248. data: {
  249. field: "name",
  250. vAlign: 1,
  251. hAlign: 0,
  252. font: "Arial"
  253. }
  254. },
  255. {
  256. width: 250,
  257. readOnly: false,
  258. head: {
  259. titleNames: ["选项"],
  260. spanCols: [1],
  261. spanRows: [1],
  262. vAlign: [1],
  263. hAlign: [1],
  264. font: ["Arial"]
  265. },
  266. data: {
  267. field: "options",
  268. vAlign: 1,
  269. hAlign: 0,
  270. font: "Arial"
  271. }
  272. }
  273. ]
  274. },
  275. headers: [
  276. {name: '施工工序', dataCode: 'name', width: 250, rateWidth: 0.5, vAlign: 'center', hAlign: 'center', formatter: '@'},
  277. {name: '选项', dataCode: 'options', width: 250, rateWidth: 0.5, vAlign: 'center', hAlign: 'left', formatter: '@'},
  278. ],
  279. rowHeaderWidth:25,
  280. events: {
  281. CellClick: function (sender, args) {
  282. if(elfItem.headers[args.col]['dataCode'] === 'options' && args.sheetArea === 3){
  283. if(!args.sheet.getCell(args.row, args.col).locked() && !args.sheet.isEditing()){
  284. args.sheet.startEdit();
  285. }
  286. }
  287. },
  288. ClipboardPasting: function (sender, info) {
  289. info.cancel = true;
  290. }
  291. }
  292. };
  293. const options = {
  294. workBook: {
  295. tabStripVisible: false,
  296. allowContextMenu: false,
  297. allowCopyPasteExcelStyle : false,
  298. allowExtendPasteRange: false,
  299. allowUserDragDrop : false,
  300. allowUserDragFill: false,
  301. scrollbarMaxAlign : true
  302. },
  303. sheet: {
  304. protectionOptions: {allowResizeRows: true, allowResizeColumns: true},
  305. clipBoardOptions: GC.Spread.Sheets.ClipboardPasteOptions.values
  306. }
  307. };
  308. //渲染时方法,停止渲染
  309. //@param {Object}sheet {Function}func @return {void}
  310. function renderSheetFunc(sheet, func){
  311. sheet.suspendEvent();
  312. sheet.suspendPaint();
  313. if(func){
  314. func();
  315. }
  316. sheet.resumeEvent();
  317. sheet.resumePaint();
  318. }
  319. //设置表选项
  320. //@param {Object}workBook {Object}opts @return {void}
  321. function setOptions (workBook, opts) {
  322. for(let opt in opts.workBook){
  323. workBook.options[opt] = opts.workBook[opt];
  324. }
  325. for(let opt in opts.sheet){
  326. workBook.getActiveSheet().options[opt] = opts.sheet[opt];
  327. }
  328. }
  329. //建表头
  330. //@param {Object}sheet {Array}headers @return {void}
  331. function buildHeader(sheet, headers) {
  332. let fuc = function () {
  333. sheet.setColumnCount(headers.length);
  334. sheet.setRowHeight(0, 30, GC.Spread.Sheets.SheetArea.colHeader);
  335. sheet.setColumnWidth(0, sheet.getParent() === bills.workBook ? 15 : 25, GC.Spread.Sheets.SheetArea.rowHeader);
  336. if(sheet.getParent() === elfItem.workBook || sheet.getParent() === guideItem.workBook){
  337. sheet.setRowHeight(0, 20, GC.Spread.Sheets.SheetArea.colHeader);
  338. }
  339. for(let i = 0, len = headers.length; i < len; i++){
  340. sheet.setValue(0, i, headers[i].name, GC.Spread.Sheets.SheetArea.colHeader);
  341. sheet.setColumnWidth(i, headers[i].width, GC.Spread.Sheets.SheetArea.colHeader);
  342. if(headers[i].formatter){
  343. sheet.setFormatter(-1, i, headers[i].formatter);
  344. }
  345. sheet.getRange(-1, i, -1, 1).hAlign(GC.Spread.Sheets.HorizontalAlign[headers[i]['hAlign']]);
  346. sheet.getRange(-1, i, -1, 1).vAlign(GC.Spread.Sheets.VerticalAlign[headers[i]['vAlign']]);
  347. }
  348. };
  349. renderSheetFunc(sheet, fuc);
  350. }
  351. //表监听事件
  352. //@param {Object}workBook @return {void}
  353. function bindEvent(workBook, events) {
  354. if(Object.keys(events).length === 0){
  355. return;
  356. }
  357. const Events = GC.Spread.Sheets.Events;
  358. for(let event in events){
  359. workBook.bind(Events[event], events[event]);
  360. }
  361. }
  362. //根据宽度比例设置列宽
  363. //@param {Object}workBook {Number}workBookWidth {Array}headers @return {void}
  364. function setColumnWidthByRate(workBook, workBookWidth, headers) {
  365. if(workBook){
  366. workBookWidth -= 48;
  367. const sheet = workBook.getActiveSheet();
  368. sheet.suspendEvent();
  369. sheet.suspendPaint();
  370. for(let col = 0; col < headers.length; col++){
  371. if(headers[col]['rateWidth'] !== undefined && headers[col]['rateWidth'] !== null && headers[col]['rateWidth'] !== ''){
  372. let width = workBookWidth * headers[col]['rateWidth'];
  373. if(headers[col]['dataCode'] === 'options'){
  374. width = width;
  375. }
  376. sheet.setColumnWidth(col, width, GC.Spread.Sheets.SheetArea.colHeader)
  377. }
  378. else {
  379. if(headers[col]['headerWidth'] !== undefined && headers[col]['headerWidth'] !== null && headers[col]['headerWidth'] !== ''){
  380. sheet.setColumnWidth(col, headers[col]['headerWidth'], GC.Spread.Sheets.SheetArea.colHeader)
  381. }
  382. }
  383. }
  384. sheet.resumeEvent();
  385. sheet.resumePaint();
  386. }
  387. }
  388. //建表
  389. //@param {Object}module @return {void}
  390. function buildSheet(module) {
  391. if(!module.workBook){
  392. module.workBook = new GC.Spread.Sheets.Workbook(module.dom[0], {sheetCount: 1});
  393. sheetCommonObj.spreadDefaultStyle(module.workBook);
  394. let sheet = module.workBook.getActiveSheet();
  395. if(module === bills){
  396. //默认初始可控制焦点在清单表中
  397. module.workBook.focus();
  398. sheet.options.isProtected = true;
  399. sheet.name('stdBillsGuidance_bills');
  400. //设置悬浮提示
  401. TREE_SHEET_HELPER.initSetting(bills.dom[0], bills.treeSetting);
  402. }
  403. if(module === guideItem){
  404. sheet.options.isProtected = true;
  405. sheet.getRange(-1, 0, -1, 1).locked(false);
  406. sheet.getRange(-1, 1, -1, 1).locked(true);
  407. }
  408. if(module === elfItem){
  409. sheet.options.isProtected = true;
  410. sheet.getRange(-1, 0, -1, 1).locked(true);
  411. sheet.getRange(-1, 1, -1, 1).locked(false);
  412. }
  413. if(module.rowHeaderWidth) sheet.setColumnWidth(0, module.rowHeaderWidth, GC.Spread.Sheets.SheetArea.rowHeader);
  414. setOptions(module.workBook, options);
  415. buildHeader(module.workBook.getActiveSheet(), module.headers);
  416. if(module === elfItem){
  417. setColumnWidthByRate(elfItem.workBook, $('#zy').width(), elfItem.headers)
  418. }
  419. bindEvent(module.workBook, module.events);
  420. }
  421. }
  422. //清空表数据
  423. //@param {Object}sheet {Array}headers {Number}rowCount @return {void}
  424. function cleanData(sheet, headers, rowCount){
  425. renderSheetFunc(sheet, function () {
  426. sheet.clear(-1, 0, -1, headers.length, GC.Spread.Sheets.SheetArea.viewport, GC.Spread.Sheets.StorageType.data);
  427. if (rowCount > 0) {
  428. sheet.setRowCount(rowCount);
  429. }
  430. });
  431. }
  432. //初始化各工作表
  433. //@param {Array}modules @return {void}
  434. function initWorkBooks(modules){
  435. for(let module of modules){
  436. buildSheet(module);
  437. }
  438. }
  439. //点击清单名称后面的问号,弹出补注窗口并设置当前节点(或xxx父节点)的补注
  440. //@param {Number}row(当前焦点行) @return {void}
  441. function initRechargeModal(row) {
  442. let node = bills.tree.items[row];
  443. while (node && !node.data.recharge){
  444. node = node.parent;
  445. }
  446. let recharge = node && node.data.recharge ? node.data.recharge : '无内容';
  447. node = bills.tree.items[row];
  448. while (node && !node.data.ruleText){
  449. node = node.parent;
  450. }
  451. let ruleText = node && node.data.ruleText ? node.data.ruleText : '无内容';
  452. $('#questionTab1').text('补注');
  453. $('#questionTab2').text('工程量计算规则');
  454. $('#questionContent1').html(recharge);
  455. $('#questionContent2').html(ruleText);
  456. $('#questionModal').modal('show');
  457. }
  458. //节点链上含有补注或工程量计算规则数据
  459. //@param {Number}row(行当前行) @return {Boolean}
  460. function hasRechargeRuleText(row) {
  461. let node = bills.tree.items[row];
  462. if (!node) {
  463. return false;
  464. }
  465. while (node) {
  466. if (node.data.recharge || node.data.ruleText) {
  467. return true;
  468. }
  469. node = node.parent;
  470. }
  471. return false;
  472. }
  473. //初始化并输出树
  474. //@param {Object}module {Object}sheet {Object}treeSetting {Array}datas
  475. function initTree(module, sheet, treeSetting, datas){
  476. module.tree = idTree.createNew({id: 'ID', pid: 'ParentID', nid: 'NextSiblingID', rootId: -1, autoUpdate: true});
  477. module.controller = TREE_SHEET_CONTROLLER.createNew(module.tree, sheet, treeSetting, false);
  478. module.tree.loadDatas(datas);
  479. if(module === bills){
  480. initExpandStat();
  481. }
  482. module.controller.showTreeData();
  483. if(module === bills){
  484. setBillsHint(bills.tree.items, stdBillsJobData, stdBillsFeatureData);
  485. renderSheetFunc(sheet, function () {
  486. for(let i = 0; i < bills.tree.items.length; i++){
  487. sheet.setCellType(i, 1, TREE_SHEET_HELPER.getQuestionCellType(initRechargeModal, hasRechargeRuleText));
  488. }
  489. });
  490. }
  491. }
  492. //项目指引表焦点控制
  493. //@param {Number}row @return {void}
  494. function guideItemInitSel(row){
  495. let billsNode = bills.tree.selected;
  496. let node = null;
  497. if(billsNode && billsNode.guidance.tree){
  498. node = billsNode.guidance.tree.items[row];
  499. if(node){
  500. billsNode.guidance.tree.selected = node;
  501. }
  502. }
  503. }
  504. //清单精灵表焦点控制
  505. //@param {Number}row @return {void}
  506. function elfItemInitSel(row){
  507. let billsNode = bills.tree.selected;
  508. let node = null;
  509. if(billsNode && billsNode.elf.tree){
  510. node = billsNode.elf.tree.items[row];
  511. if(node){
  512. billsNode.elf.tree.selected = node;
  513. }
  514. }
  515. }
  516. //根据项目指引的类型设置单元格类型,定额类型的项目指引为复选框
  517. //@param {Array}nodes @return {void}
  518. function setItemCellType(nodes){
  519. //设置单元格类型
  520. const base = new GC.Spread.Sheets.CellTypes.Base();
  521. const checkBox = new GC.Spread.Sheets.CellTypes.CheckBox();
  522. const sheet = guideItem.workBook.getActiveSheet();
  523. renderSheetFunc(sheet, function(){
  524. for(let node of nodes){
  525. sheet.setCellType(node.serialNo(), 0, node.data.type === itemType.ration ? checkBox : base);
  526. }
  527. });
  528. }
  529. //初始化清单的工作内容和项目特征
  530. //@param {Number}billsLibId {Function}callback @return {void}
  531. function initJobAndCharacter(billsLibId, callback){
  532. CommonAjax.post('/stdBillsEditor/getJobContent', {userId: userID, billsLibId: billsLibId}, function (datas) {
  533. stdBillsJobData = datas;
  534. CommonAjax.post('/stdBillsEditor/getItemCharacter', {userId: userID, billsLibId: billsLibId}, function (datas) {
  535. stdBillsFeatureData = datas;
  536. if(callback){
  537. callback();
  538. }
  539. });
  540. });
  541. }
  542. //初始化清单展开收起状态
  543. //@return {void}
  544. function initExpandStat(){
  545. //读取展开收起状态
  546. let currentExpState = sessionStorage.getItem('stdBillsGuidanceExpState');
  547. if(currentExpState){
  548. bills.tree.setExpandedByState(bills.tree.items, currentExpState);
  549. }
  550. //非叶子节点默认收起
  551. else{
  552. bills.tree.setRootExpanded(bills.tree.roots, false);
  553. }
  554. }
  555. //设置tag以悬浮提示
  556. function setTagForHint(nodes){
  557. let sheet = bills.workBook.getActiveSheet();
  558. renderSheetFunc(sheet, function () {
  559. for(let node of nodes){
  560. sheet.setTag(node.serialNo(), 2, node.data.ruleText ? node.data.ruleText : '');
  561. }
  562. });
  563. }
  564. //根据编码定位至清单精灵库中
  565. //@param {String}code @return {void}
  566. function locateAtBills(code) {
  567. let nineCode = code.substring(0, 9);
  568. let items = bills.tree.items;
  569. let locateBills = _.find(items, function(item){
  570. return item.data.code === nineCode;
  571. });
  572. if(locateBills){
  573. expandSearchNodes([locateBills]);
  574. sessionStorage.setItem('stdBillsGuidanceExpState', bills.tree.getExpState(bills.tree.items));
  575. }
  576. let sheet = bills.workBook.getActiveSheet();
  577. let locateRow = locateBills ? locateBills.serialNo() : 0;
  578. sheet.setActiveCell(locateRow, 0);
  579. sheet.showRow(locateRow, GC.Spread.Sheets.VerticalPosition.center);
  580. }
  581. //清单设置悬浮提示信息
  582. //@param {Array}billsNodes(清单节点) {Array}jobs(总的工作内容数据) {Array}items(总的项目特征数据)
  583. function setBillsHint(billsNodes, jobs, items) {
  584. let jobsMapping = {},
  585. itemsMapping = {};
  586. for(let job of jobs){
  587. jobsMapping[job.id] = job;
  588. }
  589. for(let item of items){
  590. itemsMapping[item.id] = item;
  591. }
  592. let tagInfo = [];
  593. for(let billsNode of billsNodes){
  594. let hintArr = [];
  595. let billsItems = billsNode.data.items;
  596. if(billsItems.length > 0){
  597. //项目特征
  598. hintArr.push('项目特征:');
  599. }
  600. let itemCount = 1,
  601. jobCount = 1;
  602. for(let billsItem of billsItems){
  603. let itemData = itemsMapping[billsItem.id];
  604. if(itemData){
  605. //特征值
  606. let eigens = [];
  607. for(let eigen of itemData.itemValue){
  608. eigens.push(eigen.value);
  609. }
  610. eigens = eigens.join(';');
  611. hintArr.push(`${itemCount}.${itemData.content}${eigens === '' ? '' : ': ' + eigens}`);
  612. itemCount ++;
  613. }
  614. }
  615. //工作内容
  616. let billsJobs = billsNode.data.jobs;
  617. if(billsJobs.length > 0){
  618. hintArr.push('工作内容:');
  619. }
  620. for(let billsJob of billsJobs){
  621. let jobData = jobsMapping[billsJob.id];
  622. if(jobData){
  623. hintArr.push(`${jobCount}.${jobData.content}`);
  624. jobCount ++;
  625. }
  626. }
  627. /*if(billsNode.data.ruleText && billsNode.data.ruleText !== ''){
  628. hintArr.push('工程量计算规则:');
  629. hintArr.push(billsNode.data.ruleText);
  630. }
  631. if(billsNode.data.recharge && billsNode.data.recharge !== ''){
  632. hintArr.push('补注:');
  633. hintArr.push(billsNode.data.recharge);
  634. }*/
  635. if(hintArr.length > 0){
  636. tagInfo.push({row: billsNode.serialNo(), value: hintArr.join('\n')});
  637. }
  638. }
  639. let sheet = bills.workBook.getActiveSheet();
  640. renderSheetFunc(sheet, function () {
  641. for(let tagI of tagInfo){
  642. sheet.setTag(tagI.row, 0, tagI.value);
  643. }
  644. });
  645. }
  646. //初始选择清单指引库
  647. //@param {Number}libID @return {void}
  648. function libInitSel(libID){
  649. //获取清单
  650. $.bootstrapLoading.start();
  651. CommonAjax.post('/billsGuidance/api/getLibWithBills', {libID: libID}, function(rstData){
  652. currentLib = rstData.guidanceLib;
  653. if(guideItem.workBook){
  654. guideItem.workBook.destroy();
  655. guideItem.workBook = null;
  656. }
  657. if(elfItem.workBook){
  658. elfItem.workBook.destroy();
  659. elfItem.workBook = null;
  660. }
  661. initViews();
  662. let callback = function () {
  663. initTree(bills, bills.workBook.getActiveSheet(), bills.treeSetting, rstData.bills);
  664. if(doAfterLoadGuidance){
  665. doAfterLoadGuidance();
  666. }
  667. $.bootstrapLoading.end();
  668. };
  669. //获取清单库中的工作内容和项目特征
  670. initJobAndCharacter(rstData.guidanceLib.billsLibId, callback);
  671. }, function () {
  672. $.bootstrapLoading.end();
  673. });
  674. }
  675. //初始化清单指引库
  676. //@param {Array}libDats @return {void}
  677. function initLibs(libDatas){
  678. libSel.empty();
  679. if(!libDatas){
  680. return;
  681. }
  682. let selectedLib = sessionStorage.getItem('stdBillsGuidance');
  683. for(let libData of libDatas){
  684. let opt = $('<option>').val(libData.id).text(libData.name);
  685. if(selectedLib && libData.id == selectedLib){
  686. opt.attr('selected', 'selected');
  687. }
  688. libSel.append(opt);
  689. }
  690. //初始默认选择
  691. libInitSel(libSel.select().val());
  692. }
  693. //初始化视图
  694. //@param {void} @return {void}
  695. function initViews(){
  696. //赋初始高度
  697. if($('#billsGuidance_bills').height() === 0 || $('#billsGuidance_items').height() === 0){
  698. let height = $(window).height()-$(".header").height()-$(".toolsbar").height()-$(".tools-bar-height-z").height();
  699. $('#billsGuidance_bills').height(height / 2);
  700. $('#billsGuidance_items').height(height / 2);
  701. }
  702. let modules = [bills];
  703. if(currentLib.type && currentLib.type === libType.elf){
  704. modules.push(elfItem);
  705. }
  706. else {
  707. modules.push(guideItem);
  708. }
  709. initWorkBooks(modules);
  710. }
  711. //展开至搜索出来点的节点
  712. //@param {Array}nodes @return {void}
  713. function expandSearchNodes(nodes){
  714. let that = this;
  715. let billsSheet = bills.workBook.getActiveSheet();
  716. renderSheetFunc(billsSheet, function () {
  717. function expParentNode(node){
  718. if(node.parent && !node.parent.expanded){
  719. node.parent.setExpanded(true);
  720. expParentNode(node.parent);
  721. }
  722. }
  723. for(let node of nodes){
  724. expParentNode(node);
  725. }
  726. TREE_SHEET_HELPER.refreshTreeNodeData(bills.treeSetting, billsSheet, bills.tree.roots, true);
  727. TREE_SHEET_HELPER.refreshNodesVisible(bills.tree.roots, billsSheet, true);
  728. });
  729. }
  730. //各按钮监听事件
  731. //@return {void}
  732. function bindBtn(){
  733. //打开清单指引库
  734. $('#stdBillsGuidanceTab').click(function () {
  735. if(libSel.children().length === 0 && !projectReadOnly && !$(this).hasClass('disabled')){
  736. initLibs(projectInfoObj.projectInfo.engineeringInfo.billsGuidance_lib);
  737. }
  738. });
  739. //更改清单指引库
  740. $('#stdBillsGuidanceLibSelect').change(function () {
  741. //关闭搜索窗口
  742. $('#billsGuidanceSearchResult').hide();
  743. billsLibObj.clearHighLight(bills.workBook);
  744. libInitSel($(this).select().val());
  745. //记住选项
  746. sessionStorage.setItem('stdBillsGuidance', $(this).select().val());
  747. //清除展开收起状态sessionStorage
  748. sessionStorage.removeItem('stdBillsGuidanceExpState');
  749. });
  750. //搜索
  751. $('#stdBillsGuidanceSearch>div>button').click(function () {
  752. if(!bills.tree){
  753. return;
  754. }
  755. let billsSheet = bills.workBook.getActiveSheet();
  756. billsLibObj.clearHighLight(bills.workBook);
  757. let keyword = $('#stdBillsGuidanceSearch>input').val();
  758. if (!keyword || keyword === '') {
  759. $('#billsGuidanceSearchResult').hide();
  760. return;
  761. }
  762. let result = bills.tree.items.filter(function (item) {
  763. let codeIs = item.data.code ? item.data.code.indexOf(keyword) !== -1 : false;
  764. let nameIs = item.data.name ? item.data.name.indexOf(keyword) !== -1 : false;
  765. return codeIs || nameIs;
  766. });
  767. result.sort(function (x, y) {
  768. return x.serialNo() - y.serialNo();
  769. });
  770. if (result.length !== 0) {
  771. //展开搜索出来的节点
  772. expandSearchNodes(result);
  773. //设置记住展开
  774. sessionStorage.setItem('stdBillsGuidanceExpState', bills.tree.getExpState(bills.tree.items));
  775. let sel = billsSheet.getSelections();
  776. renderSheetFunc(billsSheet, function () {
  777. bills.controller.setTreeSelected(result[0]);
  778. billsSheet.setSelection(result[0].serialNo(), sel[0].col, 1, 1);
  779. for (let node of result) {
  780. billsSheet.getRange(node.serialNo(), -1, 1, -1).backColor('lemonChiffon');
  781. }
  782. });
  783. //搜索初始定位
  784. billsSheet.showRow(result[0].serialNo(), GC.Spread.Sheets.VerticalPosition.bottom);
  785. $('#nextBillsGuidance').show();
  786. $('#nextBillsGuidance').unbind('click');
  787. $('#nextBillsGuidance').bind('click', function () {
  788. let cur = bills.tree.selected, resultIndex = result.indexOf(cur), sel = billsSheet.getSelections();
  789. if (resultIndex === result.length - 1) {
  790. bills.controller.setTreeSelected(result[0]);
  791. billsSheet.setSelection(result[0].serialNo(), sel[0].col, 1, 1);
  792. billsSheet.showRow(result[0].serialNo(), GC.Spread.Sheets.VerticalPosition.bottom);
  793. } else {
  794. bills.controller.setTreeSelected(result[resultIndex + 1]);
  795. billsSheet.setSelection(result[resultIndex + 1].serialNo(), sel[0].col, 1, 1);
  796. billsSheet.showRow(result[resultIndex + 1].serialNo(), GC.Spread.Sheets.VerticalPosition.bottom);
  797. }
  798. });
  799. } else {
  800. billsLibObj.clearHighLight(bills.workBook);
  801. $('#nextBillsGuidance').hide();
  802. }
  803. $('#billsGuidanceSearchResultCount').text('搜索结果:' + result.length);
  804. $('#billsGuidanceSearchResult').show();
  805. });
  806. //搜索框回车
  807. $('#stdBillsGuidanceSearch>input').bind('keypress', function (event) {
  808. if(event.keyCode === 13){
  809. $(this).blur();
  810. $('#stdBillsGuidanceSearch>div>button').click();
  811. }
  812. });
  813. // 关闭搜索结果
  814. $('#closeSearchBillsGuidance').click(function () {
  815. $('#billsGuidanceSearchResult').hide();
  816. billsLibObj.clearHighLight(bills.workBook);
  817. refreshWorkBook();
  818. });
  819. }
  820. //刷新表
  821. //@return {void}
  822. function refreshWorkBook(){
  823. if(bills.workBook){
  824. bills.workBook.refresh();
  825. }
  826. if(guideItem.workBook){
  827. guideItem.workBook.refresh();
  828. }
  829. if(elfItem.workBook){
  830. elfItem.workBook.refresh();
  831. }
  832. }
  833. return {initViews, bindBtn, refreshWorkBook, setColumnWidthByRate, locateAtBills, bills, elfItem};
  834. })();
  835. $(document).ready(function(){
  836. billsGuidance.bindBtn();
  837. });