std_billsGuidance_lib.js 33 KB

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