std_billsGuidance_lib.js 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871
  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:1,
  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. sheet.options.rowHeaderVisible = false;
  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) {
  414. sheet.setColumnWidth(0, module.rowHeaderWidth, GC.Spread.Sheets.SheetArea.rowHeader);
  415. }
  416. setOptions(module.workBook, options);
  417. buildHeader(module.workBook.getActiveSheet(), module.headers);
  418. if(module === elfItem){
  419. setColumnWidthByRate(elfItem.workBook, $('#zy').width(), elfItem.headers)
  420. }
  421. bindEvent(module.workBook, module.events);
  422. }
  423. }
  424. //清空表数据
  425. //@param {Object}sheet {Array}headers {Number}rowCount @return {void}
  426. function cleanData(sheet, headers, rowCount){
  427. renderSheetFunc(sheet, function () {
  428. sheet.clear(-1, 0, -1, headers.length, GC.Spread.Sheets.SheetArea.viewport, GC.Spread.Sheets.StorageType.data);
  429. if (rowCount > 0) {
  430. sheet.setRowCount(rowCount);
  431. }
  432. });
  433. }
  434. //初始化各工作表
  435. //@param {Array}modules @return {void}
  436. function initWorkBooks(modules){
  437. for(let module of modules){
  438. buildSheet(module);
  439. }
  440. }
  441. //点击清单名称后面的问号,弹出补注窗口并设置当前节点(或xxx父节点)的补注
  442. //@param {Number}row(当前焦点行) @return {void}
  443. function initRechargeModal(row) {
  444. let node = bills.tree.items[row];
  445. while (node && !node.data.recharge){
  446. node = node.parent;
  447. }
  448. let recharge = node && node.data.recharge ? node.data.recharge : '无内容';
  449. node = bills.tree.items[row];
  450. while (node && !node.data.ruleText){
  451. node = node.parent;
  452. }
  453. let ruleText = node && node.data.ruleText ? node.data.ruleText : '无内容';
  454. $('#questionTab1').text('补注');
  455. $('#questionTab2').text('工程量计算规则');
  456. $('#questionContent1').html(recharge);
  457. $('#questionContent2').html(ruleText);
  458. $('#questionModal').modal('show');
  459. }
  460. //节点链上含有补注或工程量计算规则数据
  461. //@param {Number}row(行当前行) @return {Boolean}
  462. function hasRechargeRuleText(row) {
  463. let node = bills.tree.items[row];
  464. if (!node) {
  465. return false;
  466. }
  467. while (node) {
  468. if (node.data.recharge || node.data.ruleText) {
  469. return true;
  470. }
  471. node = node.parent;
  472. }
  473. return false;
  474. }
  475. //初始化并输出树
  476. //@param {Object}module {Object}sheet {Object}treeSetting {Array}datas
  477. function initTree(module, sheet, treeSetting, datas){
  478. module.tree = idTree.createNew({id: 'ID', pid: 'ParentID', nid: 'NextSiblingID', rootId: -1, autoUpdate: true});
  479. module.controller = TREE_SHEET_CONTROLLER.createNew(module.tree, sheet, treeSetting, false);
  480. module.tree.loadDatas(datas);
  481. if(module === bills){
  482. initExpandStat();
  483. }
  484. module.controller.showTreeData();
  485. if(module === bills){
  486. module.workBook.getSheet(0).options.rowHeaderVisible = true;
  487. setBillsHint(bills.tree.items, stdBillsJobData, stdBillsFeatureData);
  488. renderSheetFunc(sheet, function () {
  489. for(let i = 0; i < bills.tree.items.length; i++){
  490. sheet.setCellType(i, 1, TREE_SHEET_HELPER.getQuestionCellType(initRechargeModal, hasRechargeRuleText));
  491. }
  492. });
  493. }
  494. }
  495. //项目指引表焦点控制
  496. //@param {Number}row @return {void}
  497. function guideItemInitSel(row){
  498. let billsNode = bills.tree.selected;
  499. let node = null;
  500. if(billsNode && billsNode.guidance.tree){
  501. node = billsNode.guidance.tree.items[row];
  502. if(node){
  503. billsNode.guidance.tree.selected = node;
  504. }
  505. }
  506. }
  507. //清单精灵表焦点控制
  508. //@param {Number}row @return {void}
  509. function elfItemInitSel(row){
  510. let billsNode = bills.tree.selected;
  511. let node = null;
  512. if(billsNode && billsNode.elf.tree){
  513. node = billsNode.elf.tree.items[row];
  514. if(node){
  515. billsNode.elf.tree.selected = node;
  516. }
  517. }
  518. }
  519. //根据项目指引的类型设置单元格类型,定额类型的项目指引为复选框
  520. //@param {Array}nodes @return {void}
  521. function setItemCellType(nodes){
  522. //设置单元格类型
  523. const base = new GC.Spread.Sheets.CellTypes.Base();
  524. const checkBox = new GC.Spread.Sheets.CellTypes.CheckBox();
  525. const sheet = guideItem.workBook.getActiveSheet();
  526. renderSheetFunc(sheet, function(){
  527. for(let node of nodes){
  528. sheet.setCellType(node.serialNo(), 0, node.data.type === itemType.ration ? checkBox : base);
  529. }
  530. });
  531. }
  532. //初始化清单的工作内容和项目特征
  533. //@param {Number}billsLibId {Function}callback @return {void}
  534. function initJobAndCharacter(billsLibId, callback){
  535. CommonAjax.post('/stdBillsEditor/getJobContent', {userId: userID, billsLibId: billsLibId}, function (datas) {
  536. stdBillsJobData = datas;
  537. CommonAjax.post('/stdBillsEditor/getItemCharacter', {userId: userID, billsLibId: billsLibId}, function (datas) {
  538. stdBillsFeatureData = datas;
  539. if(callback){
  540. callback();
  541. }
  542. });
  543. });
  544. }
  545. //初始化清单展开收起状态
  546. //@return {void}
  547. function initExpandStat(){
  548. //读取展开收起状态
  549. let currentExpState = sessionStorage.getItem('stdBillsGuidanceExpState');
  550. if(currentExpState){
  551. bills.tree.setExpandedByState(bills.tree.items, currentExpState);
  552. }
  553. //非叶子节点默认收起
  554. else{
  555. bills.tree.setRootExpanded(bills.tree.roots, false);
  556. }
  557. }
  558. //设置tag以悬浮提示
  559. function setTagForHint(nodes){
  560. let sheet = bills.workBook.getActiveSheet();
  561. renderSheetFunc(sheet, function () {
  562. for(let node of nodes){
  563. sheet.setTag(node.serialNo(), 2, node.data.ruleText ? node.data.ruleText : '');
  564. }
  565. });
  566. }
  567. //根据编码定位至清单精灵库中
  568. //@param {String}code @return {void}
  569. function locateAtBills(code) {
  570. let nineCode = code.substring(0, 9);
  571. let items = bills.tree.items;
  572. let locateBills = _.find(items, function(item){
  573. return item.data.code === nineCode;
  574. });
  575. if(locateBills){
  576. expandSearchNodes([locateBills]);
  577. sessionStorage.setItem('stdBillsGuidanceExpState', bills.tree.getExpState(bills.tree.items));
  578. }
  579. let sheet = bills.workBook.getActiveSheet();
  580. let locateRow = locateBills ? locateBills.serialNo() : 0;
  581. sheet.setActiveCell(locateRow, 0);
  582. sheet.showRow(locateRow, GC.Spread.Sheets.VerticalPosition.center);
  583. }
  584. //清单设置悬浮提示信息
  585. //@param {Array}billsNodes(清单节点) {Array}jobs(总的工作内容数据) {Array}items(总的项目特征数据)
  586. function setBillsHint(billsNodes, jobs, items) {
  587. let jobsMapping = {},
  588. itemsMapping = {};
  589. for(let job of jobs){
  590. jobsMapping[job.id] = job;
  591. }
  592. for(let item of items){
  593. itemsMapping[item.id] = item;
  594. }
  595. let tagInfo = [];
  596. for(let billsNode of billsNodes){
  597. let hintArr = [];
  598. let billsItems = billsNode.data.items;
  599. if(billsItems.length > 0){
  600. //项目特征
  601. hintArr.push('项目特征:');
  602. }
  603. let itemCount = 1,
  604. jobCount = 1;
  605. for(let billsItem of billsItems){
  606. let itemData = itemsMapping[billsItem.id];
  607. if(itemData){
  608. //特征值
  609. let eigens = [];
  610. for(let eigen of itemData.itemValue){
  611. eigens.push(eigen.value);
  612. }
  613. eigens = eigens.join(';');
  614. hintArr.push(`${itemCount}.${itemData.content}${eigens === '' ? '' : ': ' + eigens}`);
  615. itemCount ++;
  616. }
  617. }
  618. //工作内容
  619. let billsJobs = billsNode.data.jobs;
  620. if(billsJobs.length > 0){
  621. hintArr.push('工作内容:');
  622. }
  623. for(let billsJob of billsJobs){
  624. let jobData = jobsMapping[billsJob.id];
  625. if(jobData){
  626. hintArr.push(`${jobCount}.${jobData.content}`);
  627. jobCount ++;
  628. }
  629. }
  630. /*if(billsNode.data.ruleText && billsNode.data.ruleText !== ''){
  631. hintArr.push('工程量计算规则:');
  632. hintArr.push(billsNode.data.ruleText);
  633. }
  634. if(billsNode.data.recharge && billsNode.data.recharge !== ''){
  635. hintArr.push('补注:');
  636. hintArr.push(billsNode.data.recharge);
  637. }*/
  638. if(hintArr.length > 0){
  639. tagInfo.push({row: billsNode.serialNo(), value: hintArr.join('\n')});
  640. }
  641. }
  642. let sheet = bills.workBook.getActiveSheet();
  643. renderSheetFunc(sheet, function () {
  644. for(let tagI of tagInfo){
  645. sheet.setTag(tagI.row, 0, tagI.value);
  646. }
  647. });
  648. }
  649. //初始选择清单指引库
  650. //@param {Number}libID @return {void}
  651. function libInitSel(libID){
  652. //获取清单
  653. $.bootstrapLoading.start();
  654. CommonAjax.post('/billsGuidance/api/getLibWithBills', {libID: libID}, function(rstData){
  655. currentLib = rstData.guidanceLib;
  656. if(guideItem.workBook){
  657. guideItem.workBook.destroy();
  658. guideItem.workBook = null;
  659. }
  660. if(elfItem.workBook){
  661. elfItem.workBook.destroy();
  662. elfItem.workBook = null;
  663. }
  664. initViews();
  665. let callback = function () {
  666. initTree(bills, bills.workBook.getActiveSheet(), bills.treeSetting, rstData.bills);
  667. if(doAfterLoadGuidance){
  668. doAfterLoadGuidance();
  669. }
  670. $.bootstrapLoading.end();
  671. };
  672. //获取清单库中的工作内容和项目特征
  673. initJobAndCharacter(rstData.guidanceLib.billsLibId, callback);
  674. }, function () {
  675. $.bootstrapLoading.end();
  676. });
  677. }
  678. //初始化清单指引库
  679. //@param {Array}libDats @return {void}
  680. function initLibs(libDatas){
  681. libSel.empty();
  682. if(!libDatas){
  683. return;
  684. }
  685. let selectedLib = sessionStorage.getItem('stdBillsGuidance');
  686. for(let libData of libDatas){
  687. let opt = $('<option>').val(libData.id).text(libData.name);
  688. if(selectedLib && libData.id == selectedLib){
  689. opt.attr('selected', 'selected');
  690. }
  691. libSel.append(opt);
  692. }
  693. //初始默认选择
  694. libInitSel(libSel.select().val());
  695. }
  696. //初始化视图
  697. //@param {void} @return {void}
  698. function initViews(){
  699. //赋初始高度
  700. if($('#billsGuidance_bills').height() === 0 || $('#billsGuidance_items').height() === 0){
  701. let height = $(window).height()-$(".header").height()-$(".toolsbar").height()-$(".tools-bar-height-z").height();
  702. $('#billsGuidance_bills').height(height / 2);
  703. $('#billsGuidance_items').height(height / 2);
  704. }
  705. let modules = [bills];
  706. if(currentLib.type && currentLib.type === libType.elf){
  707. modules.push(elfItem);
  708. }
  709. else {
  710. modules.push(guideItem);
  711. }
  712. initWorkBooks(modules);
  713. }
  714. //展开至搜索出来点的节点
  715. //@param {Array}nodes @return {void}
  716. function expandSearchNodes(nodes){
  717. let that = this;
  718. let billsSheet = bills.workBook.getActiveSheet();
  719. renderSheetFunc(billsSheet, function () {
  720. function expParentNode(node){
  721. if(node.parent){
  722. if (!node.parent.expanded) {
  723. node.parent.setExpanded(true);
  724. }
  725. expParentNode(node.parent);
  726. }
  727. }
  728. for(let node of nodes){
  729. expParentNode(node);
  730. }
  731. TREE_SHEET_HELPER.refreshTreeNodeData(bills.treeSetting, billsSheet, bills.tree.roots, true);
  732. TREE_SHEET_HELPER.refreshNodesVisible(bills.tree.roots, billsSheet, true);
  733. });
  734. }
  735. //各按钮监听事件
  736. //@return {void}
  737. function bindBtn(){
  738. //打开清单指引库
  739. $('#stdBillsGuidanceTab').click(function () {
  740. if(libSel.children().length === 0 && !$(this).hasClass('disabled')){
  741. initLibs(projectInfoObj.projectInfo.engineeringInfo.billsGuidance_lib);
  742. }
  743. });
  744. //更改清单指引库
  745. $('#stdBillsGuidanceLibSelect').change(function () {
  746. //关闭搜索窗口
  747. $('#billsGuidanceSearchResult').hide();
  748. billsLibObj.clearHighLight(bills.workBook);
  749. libInitSel($(this).select().val());
  750. //记住选项
  751. sessionStorage.setItem('stdBillsGuidance', $(this).select().val());
  752. //清除展开收起状态sessionStorage
  753. sessionStorage.removeItem('stdBillsGuidanceExpState');
  754. });
  755. //搜索
  756. $('#stdBillsGuidanceSearch>div>button').click(function () {
  757. if(!bills.tree){
  758. return;
  759. }
  760. let billsSheet = bills.workBook.getActiveSheet();
  761. billsLibObj.clearHighLight(bills.workBook);
  762. let keyword = $('#stdBillsGuidanceSearch>input').val();
  763. if (!keyword || keyword === '') {
  764. $('#billsGuidanceSearchResult').hide();
  765. return;
  766. }
  767. let result = bills.tree.items.filter(function (item) {
  768. let codeIs = item.data.code ? item.data.code.indexOf(keyword) !== -1 : false;
  769. let nameIs = item.data.name ? item.data.name.indexOf(keyword) !== -1 : false;
  770. return codeIs || nameIs;
  771. });
  772. result.sort(function (x, y) {
  773. return x.serialNo() - y.serialNo();
  774. });
  775. if (result.length !== 0) {
  776. //展开搜索出来的节点
  777. expandSearchNodes(result);
  778. //设置记住展开
  779. sessionStorage.setItem('stdBillsGuidanceExpState', bills.tree.getExpState(bills.tree.items));
  780. let sel = billsSheet.getSelections();
  781. renderSheetFunc(billsSheet, function () {
  782. bills.controller.setTreeSelected(result[0]);
  783. billsSheet.setSelection(result[0].serialNo(), sel[0].col, 1, 1);
  784. for (let node of result) {
  785. billsSheet.getRange(node.serialNo(), -1, 1, -1).backColor('lemonChiffon');
  786. }
  787. });
  788. //搜索初始定位
  789. billsSheet.showRow(result[0].serialNo(), GC.Spread.Sheets.VerticalPosition.bottom);
  790. //查找下一条
  791. $('#nextBillsGuidance').show();
  792. $('#nextBillsGuidance').unbind('click');
  793. $('#nextBillsGuidance').bind('click', function () {
  794. let cur = bills.tree.selected, resultIndex = result.indexOf(cur), sel = billsSheet.getSelections();
  795. if (resultIndex === result.length - 1) {
  796. bills.controller.setTreeSelected(result[0]);
  797. billsSheet.setSelection(result[0].serialNo(), sel[0].col, 1, 1);
  798. billsSheet.showRow(result[0].serialNo(), GC.Spread.Sheets.VerticalPosition.bottom);
  799. } else {
  800. bills.controller.setTreeSelected(result[resultIndex + 1]);
  801. billsSheet.setSelection(result[resultIndex + 1].serialNo(), sel[0].col, 1, 1);
  802. billsSheet.showRow(result[resultIndex + 1].serialNo(), GC.Spread.Sheets.VerticalPosition.bottom);
  803. }
  804. });
  805. //查找上一条
  806. $('#preBillsGuidance').show();
  807. $('#preBillsGuidance').unbind('click');
  808. $('#preBillsGuidance').bind('click', function () {
  809. let cur = bills.tree.selected, resultIndex = result.indexOf(cur), sel = billsSheet.getSelections();
  810. if (resultIndex === 0) {
  811. bills.controller.setTreeSelected(result[result.length - 1]);
  812. billsSheet.setSelection(result[result.length - 1].serialNo(), sel[0].col, 1, 1);
  813. billsSheet.showRow(result[result.length - 1].serialNo(), GC.Spread.Sheets.VerticalPosition.bottom);
  814. } else {
  815. bills.controller.setTreeSelected(result[resultIndex - 1]);
  816. billsSheet.setSelection(result[resultIndex - 1].serialNo(), sel[0].col, 1, 1);
  817. billsSheet.showRow(result[resultIndex - 1].serialNo(), GC.Spread.Sheets.VerticalPosition.bottom);
  818. }
  819. });
  820. } else {
  821. billsLibObj.clearHighLight(bills.workBook);
  822. $('#nextBillsGuidance').hide();
  823. $('#preBillsGuidance').hide();
  824. }
  825. $('#billsGuidanceSearchResultCount').text('搜索结果:' + result.length);
  826. $('#billsGuidanceSearchResult').show();
  827. autoFlashHeight();
  828. refreshWorkBook();
  829. });
  830. //搜索框回车
  831. $('#stdBillsGuidanceSearch>input').bind('keypress', function (event) {
  832. if(event.keyCode === 13){
  833. $(this).blur();
  834. $('#stdBillsGuidanceSearch>div>button').click();
  835. }
  836. });
  837. // 关闭搜索结果
  838. $('#closeSearchBillsGuidance').click(function () {
  839. $('#billsGuidanceSearchResult').hide();
  840. billsLibObj.clearHighLight(bills.workBook);
  841. autoFlashHeight();
  842. refreshWorkBook();
  843. });
  844. }
  845. //刷新表
  846. //@return {void}
  847. function refreshWorkBook(){
  848. if(bills.workBook){
  849. bills.workBook.refresh();
  850. }
  851. if(guideItem.workBook){
  852. guideItem.workBook.refresh();
  853. }
  854. if(elfItem.workBook){
  855. elfItem.workBook.refresh();
  856. }
  857. }
  858. return {initViews, bindBtn, refreshWorkBook, setColumnWidthByRate, locateAtBills, bills, elfItem};
  859. })();
  860. $(document).ready(function(){
  861. billsGuidance.bindBtn();
  862. });