std_billsGuidance_lib.js 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607
  1. 'use strict';
  2. /**
  3. *
  4. *
  5. * @author Zhong
  6. * @date 2018/6/11
  7. * @version
  8. */
  9. const billsGuidance = (function () {
  10. const libSel = $('#stdBillsGuidanceLibSelect');
  11. //工作内容
  12. let stdBillsJobData = [];
  13. //项目特征
  14. let stdBillsFeatureData = [];
  15. const bills = {
  16. dom: $('#billsGuidance_bills'),
  17. workBook: null,
  18. cache: [],
  19. tree: null,
  20. controller: null,
  21. treeSetting: {
  22. treeCol: 0,
  23. emptyRows: 0,
  24. headRows: 1,
  25. headRowHeight: [40],
  26. defaultRowHeight: 21,
  27. cols: [{
  28. width: 200,
  29. readOnly: true,
  30. head: {
  31. titleNames: ["项目编码"],
  32. spanCols: [1],
  33. spanRows: [1],
  34. vAlign: [1],
  35. hAlign: [1],
  36. font: ["Arial"]
  37. },
  38. data: {
  39. field: "code",
  40. vAlign: 1,
  41. hAlign: 0,
  42. font: "Arial"
  43. }
  44. }, {
  45. width: 200,
  46. readOnly: true,
  47. head: {
  48. titleNames: ["项目名称"],
  49. spanCols: [1],
  50. spanRows: [1],
  51. vAlign: [1],
  52. hAlign: [1],
  53. font: ["Arial"]
  54. },
  55. data: {
  56. field: "name",
  57. vAlign: 1,
  58. hAlign: 0,
  59. font: "Arial"
  60. }
  61. }]
  62. },
  63. headers: [
  64. {name: '项目编码', dataCode: 'code', width: 200, vAlign: 'center', hAlign: 'left', formatter: '@'},
  65. {name: '项目名称', dataCode: 'name', width: 200, vAlign: 'center', hAlign: 'left', formatter: '@'}
  66. ],
  67. events: {
  68. SelectionChanging: function (sender, info) {
  69. billsInitSel(info.newSelections[0].row);
  70. },
  71. CellDoubleClick: function (sender, args) {
  72. let node = bills.tree.items[args.row];
  73. if(!node){
  74. return;
  75. }
  76. if(node.children.length === 0){
  77. //插入清单
  78. let insert = billsLibObj.insertBills(stdBillsJobData, stdBillsFeatureData, node);
  79. if(insert){
  80. //插入选中的定额
  81. let addRationDatas = getInsertRationData(getCheckedRows());
  82. insertRations(addRationDatas);
  83. }
  84. }
  85. else {
  86. node.setExpanded(!node.expanded);
  87. //设置展开收起状态
  88. sessionStorage.setItem('stdBillsGuidanceExpState', bills.tree.getExpState(bills.tree.items));
  89. renderSheetFunc(args.sheet, function () {
  90. let iCount = node.posterityCount(), i, child;
  91. for (i = 0; i < iCount; i++) {
  92. child = bills.tree.items[args.row + i + 1];
  93. args.sheet.setRowVisible(args.row + i + 1, child.visible, args.sheetArea);
  94. }
  95. args.sheet.invalidateLayout();
  96. });
  97. args.sheet.repaint();
  98. }
  99. }
  100. }
  101. };
  102. //项目指引类型
  103. const itemType = {
  104. job: 0,
  105. ration: 1
  106. };
  107. const guideItem = {
  108. dom: $('#billsGuidance_items'),
  109. workBook: null,
  110. tree: null,
  111. controller: null,
  112. treeSetting: {
  113. treeCol: 0,
  114. emptyRows: 0,
  115. headRows: 1,
  116. headRowHeight: [40],
  117. defaultRowHeight: 21,
  118. cols: [{
  119. width: 300,
  120. readOnly: false,
  121. head: {
  122. titleNames: ["项目指引"],
  123. spanCols: [1],
  124. spanRows: [1],
  125. vAlign: [1],
  126. hAlign: [1],
  127. font: ["Arial"]
  128. },
  129. data: {
  130. field: "name",
  131. vAlign: 1,
  132. hAlign: 0,
  133. font: "Arial"
  134. }
  135. },
  136. {
  137. width: 50,
  138. readOnly: false,
  139. head: {
  140. titleNames: ["选择"],
  141. spanCols: [1],
  142. spanRows: [1],
  143. vAlign: [1],
  144. hAlign: [1],
  145. font: ["Arial"]
  146. },
  147. data: {
  148. field: "select",
  149. vAlign: 1,
  150. hAlign: 1,
  151. font: "Arial"
  152. }
  153. }
  154. ]
  155. },
  156. headers: [
  157. {name: '项目指引', dataCode: 'name', width: 300, vAlign: 'center', hAlign: 'left', formatter: '@'},
  158. {name: '选择', dataCode: 'select', width: 50, vAlign: 'center', hAlign: 'center', formatter: '@'},
  159. ],
  160. events: {
  161. EditStarting: function (sender, args) {
  162. if(guideItem.headers[args.col]['dataCode'] === 'name'){
  163. args.cancel = true;
  164. }
  165. },
  166. ButtonClicked: function (sender, args) {
  167. if(args.sheet.isEditing()){
  168. args.sheet.endEdit(true);
  169. }
  170. },
  171. CellDoubleClick: function (sender, args) {
  172. if(!bills.tree.selected){
  173. return;
  174. }
  175. let node = bills.tree.selected.guidance.tree.selected;
  176. if(!node){
  177. return;
  178. }
  179. if(node.children.length === 0){
  180. if(guideItem.headers[args.col]['dataCode'] === 'name'){
  181. insertRations(getInsertRationData([args.row]));
  182. }
  183. }
  184. else {
  185. node.setExpanded(!node.expanded);
  186. renderSheetFunc(args.sheet, function () {
  187. let iCount = node.posterityCount(), i, child;
  188. for (i = 0; i < iCount; i++) {
  189. child = bills.tree.selected.guidance.tree.items[args.row + i + 1];
  190. args.sheet.setRowVisible(args.row + i + 1, child.visible, args.sheetArea);
  191. }
  192. args.sheet.invalidateLayout();
  193. });
  194. args.sheet.repaint();
  195. }
  196. }
  197. }
  198. };
  199. const options = {
  200. workBook: {
  201. tabStripVisible: false,
  202. allowContextMenu: false,
  203. allowCopyPasteExcelStyle : false,
  204. allowExtendPasteRange: false,
  205. allowUserDragDrop : false,
  206. allowUserDragFill: false,
  207. scrollbarMaxAlign : true
  208. },
  209. sheet: {
  210. protectionOptions: {allowResizeRows: true, allowResizeColumns: true},
  211. clipBoardOptions: GC.Spread.Sheets.ClipboardPasteOptions.values
  212. }
  213. };
  214. //渲染时方法,停止渲染
  215. //@param {Object}sheet {Function}func @return {void}
  216. function renderSheetFunc(sheet, func){
  217. sheet.suspendEvent();
  218. sheet.suspendPaint();
  219. if(func){
  220. func();
  221. }
  222. sheet.resumeEvent();
  223. sheet.resumePaint();
  224. }
  225. //设置表选项
  226. //@param {Object}workBook {Object}opts @return {void}
  227. function setOptions (workBook, opts) {
  228. for(let opt in opts.workBook){
  229. workBook.options[opt] = opts.workBook[opt];
  230. }
  231. for(let opt in opts.sheet){
  232. workBook.getActiveSheet().options[opt] = opts.sheet[opt];
  233. }
  234. }
  235. //建表头
  236. //@param {Object}sheet {Array}headers @return {void}
  237. function buildHeader(sheet, headers) {
  238. let fuc = function () {
  239. sheet.setColumnCount(headers.length);
  240. sheet.setRowHeight(0, 40, GC.Spread.Sheets.SheetArea.colHeader);
  241. for(let i = 0, len = headers.length; i < len; i++){
  242. sheet.setValue(0, i, headers[i].name, GC.Spread.Sheets.SheetArea.colHeader);
  243. sheet.setColumnWidth(i, headers[i].width, GC.Spread.Sheets.SheetArea.colHeader);
  244. if(headers[i].formatter){
  245. sheet.setFormatter(-1, i, headers[i].formatter);
  246. }
  247. sheet.getRange(-1, i, -1, 1).hAlign(GC.Spread.Sheets.HorizontalAlign[headers[i]['hAlign']]);
  248. sheet.getRange(-1, i, -1, 1).vAlign(GC.Spread.Sheets.VerticalAlign[headers[i]['vAlign']]);
  249. }
  250. };
  251. renderSheetFunc(sheet, fuc);
  252. }
  253. //表监听事件
  254. //@param {Object}workBook @return {void}
  255. function bindEvent(workBook, events) {
  256. if(Object.keys(events).length === 0){
  257. return;
  258. }
  259. const Events = GC.Spread.Sheets.Events;
  260. for(let event in events){
  261. workBook.bind(Events[event], events[event]);
  262. }
  263. }
  264. //建表
  265. //@param {Object}module @return {void}
  266. function buildSheet(module) {
  267. if(!module.workBook){
  268. module.workBook = new GC.Spread.Sheets.Workbook(module.dom[0], {sheetCount: 1});
  269. let sheet = module.workBook.getActiveSheet();
  270. if(module === bills){
  271. //默认初始可控制焦点在清单表中
  272. module.workBook.focus();
  273. sheet.options.isProtected = true;
  274. sheet.name('stdBillsGuidance_bills');
  275. }
  276. if(module === guideItem){
  277. sheet.options.isProtected = true;
  278. sheet.getRange(-1, 1, -1, 1).locked(false);
  279. sheet.getRange(-1, 0, -1, 1).locked(true);
  280. }
  281. setOptions(module.workBook, options);
  282. buildHeader(module.workBook.getActiveSheet(), module.headers);
  283. bindEvent(module.workBook, module.events);
  284. }
  285. }
  286. //清空表数据
  287. //@param {Object}sheet {Array}headers {Number}rowCount @return {void}
  288. function cleanData(sheet, headers, rowCount){
  289. renderSheetFunc(sheet, function () {
  290. sheet.clear(-1, 0, -1, headers.length, GC.Spread.Sheets.SheetArea.viewport, GC.Spread.Sheets.StorageType.data);
  291. if (rowCount > 0) {
  292. sheet.setRowCount(rowCount);
  293. }
  294. });
  295. }
  296. //初始化各工作表
  297. //@param {Array}modules @return {void}
  298. function initWorkBooks(modules){
  299. for(let module of modules){
  300. buildSheet(module);
  301. }
  302. }
  303. //初始化并输出树
  304. //@param {Object}module {Object}sheet {Object}treeSetting {Array}datas
  305. function initTree(module, sheet, treeSetting, datas){
  306. module.tree = idTree.createNew({id: 'ID', pid: 'ParentID', nid: 'NextSiblingID', rootId: -1, autoUpdate: true});
  307. module.controller = TREE_SHEET_CONTROLLER.createNew(module.tree, sheet, treeSetting);
  308. module.tree.loadDatas(datas);
  309. if(module === bills){
  310. initExpandStat();
  311. }
  312. module.controller.showTreeData();
  313. }
  314. //项目指引表焦点控制
  315. //@param {Number}row @return {void}
  316. function guideItemInitSel(row){
  317. let billsNode = bills.tree.selected;
  318. let node = null;
  319. if(billsNode && billsNode.guidance.tree){
  320. node = billsNode.guidance.tree.items[row];
  321. if(node){
  322. billsNode.guidance.tree.selected = node;
  323. }
  324. }
  325. }
  326. //根据项目指引的类型设置单元格类型,定额类型的项目指引为复选框
  327. //@param {Array}nodes @return {void}
  328. function setItemCellType(nodes){
  329. //设置单元格类型
  330. const base = new GC.Spread.Sheets.CellTypes.Base();
  331. const checkBox = new GC.Spread.Sheets.CellTypes.CheckBox();
  332. const sheet = guideItem.workBook.getActiveSheet();
  333. renderSheetFunc(sheet, function(){
  334. for(let node of nodes){
  335. sheet.setCellType(node.serialNo(), 1, node.data.type === itemType.ration ? checkBox : base);
  336. }
  337. });
  338. }
  339. //清单表焦点控制
  340. //@param {Number}row @return {void}
  341. function billsInitSel(row){
  342. let guideSheet = guideItem.workBook.getActiveSheet();
  343. cleanData(guideSheet, guideItem.headers, -1);
  344. let node = bills.tree.items[row];
  345. if(!node){
  346. return;
  347. }
  348. bills.tree.selected = node;
  349. if(!node.guidance.tree){
  350. CommonAjax.post('/billsGuidance/api/getItemsByBills', {guidanceLibID: libSel.val(), billsID: node.getID()}, function (rstData) {
  351. initTree(node.guidance, guideSheet, guideItem.treeSetting, rstData);
  352. setItemCellType(node.guidance.tree.items);
  353. //项目指引初始焦点
  354. guideItemInitSel(guideSheet.getActiveRowIndex() ? guideSheet.getActiveRowIndex() : 0);
  355. });
  356. }
  357. else{
  358. node.guidance.controller.showTreeData();
  359. setItemCellType(node.guidance.tree.items);
  360. //项目指引初始焦点
  361. guideItemInitSel(guideSheet.getActiveRowIndex() ? guideSheet.getActiveRowIndex() : 0);
  362. }
  363. }
  364. //初始化清单的工作内容和项目特征
  365. //@param {Number}billsLibId @return {void}
  366. function initJobAndCharacter(billsLibId){
  367. CommonAjax.post('/stdBillsEditor/getJobContent', {userId: userID, billsLibId: billsLibId}, function (datas) {
  368. stdBillsJobData = datas;
  369. });
  370. CommonAjax.post('/stdBillsEditor/getItemCharacter', {userId: userID, billsLibId: billsLibId}, function (datas) {
  371. stdBillsFeatureData = datas;
  372. });
  373. }
  374. //初始化清单展开收起状态
  375. //@return {void}
  376. function initExpandStat(){
  377. //读取展开收起状态
  378. let currentExpState = sessionStorage.getItem('stdBillsGuidanceExpState');
  379. if(currentExpState){
  380. bills.tree.setExpandedByState(bills.tree.items, currentExpState);
  381. }
  382. //非叶子节点默认收起
  383. else{
  384. bills.tree.setRootExpanded(bills.tree.roots, false);
  385. }
  386. }
  387. //初始选择清单指引库
  388. //@param {Number}libID @return {void}
  389. function libInitSel(libID){
  390. //获取清单
  391. CommonAjax.post('/billsGuidance/api/getLibWithBills', {libID: libID}, function(rstData){
  392. //获取清单库中的工作内容和项目特征
  393. initJobAndCharacter(rstData.guidanceLib.billsLibId);
  394. initTree(bills, bills.workBook.getActiveSheet(), bills.treeSetting, rstData.bills);
  395. //每一棵项目指引树挂在清单节点上
  396. for(let node of bills.tree.items){
  397. node.guidance = {tree: null, controller: null};
  398. }
  399. //默认初始节点
  400. billsInitSel(0);
  401. });
  402. }
  403. //初始化清单指引库
  404. //@param {Array}libDats @return {void}
  405. function initLibs(libDatas){
  406. libSel.empty();
  407. let selectedLib = sessionStorage.getItem('stdBillsGuidance');
  408. for(let libData of libDatas){
  409. let opt = $('<option>').val(libData.id).text(libData.name);
  410. if(selectedLib && libData.id == selectedLib){
  411. opt.attr('selected', 'selected');
  412. }
  413. libSel.append(opt);
  414. }
  415. //初始默认选择
  416. libInitSel(libSel.select().val());
  417. }
  418. //初始化视图
  419. //@param {void} @return {void}
  420. function initViews(){
  421. let modules = [bills, guideItem];
  422. initWorkBooks(modules);
  423. }
  424. //获取选中的行
  425. //@return {Array}
  426. function getCheckedRows(){
  427. let rst = [];
  428. let itemSheet = guideItem.workBook.getActiveSheet();
  429. for(let row = 0; row < itemSheet.getRowCount(); row++){
  430. let rowV = itemSheet.getValue(row, 1);
  431. if(rowV){
  432. rst.push(row);
  433. }
  434. }
  435. return rst;
  436. }
  437. //获取选中的定额数据
  438. //@param {Array}rows @return {Array}
  439. function getInsertRationData(rows){
  440. let rst = [];
  441. for(let row of rows){
  442. let node = bills.tree.selected.guidance.tree.items[row];
  443. if(node && node.data.type === itemType.ration){
  444. rst.push({itemQuery: {userID: userID, ID: node.data.rationID}, rationType: rationType.ration});
  445. }
  446. }
  447. return rst;
  448. }
  449. //插入定额
  450. //@return {void}
  451. function insertRations(addRationDatas){
  452. if(addRationDatas.length > 0){
  453. projectObj.project.Ration.addMultiRation(addRationDatas, function () {
  454. //恢复
  455. let sheet = guideItem.workBook.getActiveSheet();
  456. renderSheetFunc(sheet, function () {
  457. for(let row = 0; row < sheet.getRowCount(); row++){
  458. if(sheet.getValue(row, 1)){
  459. sheet.setValue(row, 1, false);
  460. }
  461. }
  462. });
  463. });
  464. }
  465. }
  466. //展开至搜索出来点的节点
  467. //@param {Array}nodes @return {void}
  468. function expandSearchNodes(nodes){
  469. let that = this;
  470. let billsSheet = bills.workBook.getActiveSheet();
  471. renderSheetFunc(billsSheet, function () {
  472. function expParentNode(node){
  473. if(node.parent && !node.parent.expanded){
  474. node.parent.setExpanded(true);
  475. expParentNode(node.parent);
  476. }
  477. }
  478. for(let node of nodes){
  479. expParentNode(node);
  480. }
  481. TREE_SHEET_HELPER.refreshTreeNodeData(bills.treeSetting, billsSheet, bills.tree.roots, true);
  482. TREE_SHEET_HELPER.refreshNodesVisible(bills.tree.roots, billsSheet, true);
  483. });
  484. }
  485. //各按钮监听事件
  486. //@return {void}
  487. function bindBtn(){
  488. //打开清单指引库
  489. $('#stdBillsGuidanceTab').click(function () {
  490. if(libSel.children().length === 0){
  491. initLibs(projectInfoObj.projectInfo.engineeringInfo.billsGuidance_lib);
  492. }
  493. });
  494. //更改清单指引库
  495. $('#stdBillsGuidanceLibSelect').change(function () {
  496. //关闭搜索窗口
  497. $('#billsGuidanceSearchResult').hide();
  498. billsLibObj.clearHighLight(bills.workBook);
  499. libInitSel($(this).select().val());
  500. //记住选项
  501. sessionStorage.setItem('stdBillsGuidance', $(this).select().val());
  502. //清除展开收起状态sessionStorage
  503. sessionStorage.removeItem('stdBillsGuidanceExpState');
  504. });
  505. //插入定额
  506. $('#guidanceInsertRation').click(function () {
  507. let addRationDatas = getInsertRationData(getCheckedRows());
  508. insertRations(addRationDatas);
  509. });
  510. //插入清单
  511. $('#guidanceInsertBills').click(function () {
  512. //插入清单
  513. if(!bills.tree.selected){
  514. return;
  515. }
  516. if(bills.tree.selected.children.length === 0){
  517. let insert = billsLibObj.insertBills(stdBillsJobData, stdBillsFeatureData, bills.tree.selected);
  518. if(insert){
  519. //插入选中的定额
  520. let addRationDatas = getInsertRationData(getCheckedRows());
  521. insertRations(addRationDatas);
  522. }
  523. }
  524. });
  525. //搜索
  526. $('#stdBillsGuidanceSearch>span>button').click(function () {
  527. let billsSheet = bills.workBook.getActiveSheet();
  528. billsLibObj.clearHighLight(bills.workBook);
  529. let keyword = $('#stdBillsGuidanceSearch>input').val();
  530. if (!keyword || keyword === '') {
  531. $('#billsGuidanceSearchResult').hide();
  532. return;
  533. }
  534. let result = bills.tree.items.filter(function (item) {
  535. let codeIs = item.data.code ? item.data.code.indexOf(keyword) !== -1 : false;
  536. let nameIs = item.data.name ? item.data.name.indexOf(keyword) !== -1 : false;
  537. return codeIs || nameIs;
  538. });
  539. result.sort(function (x, y) {
  540. return x.serialNo() - y.serialNo();
  541. });
  542. if (result.length !== 0) {
  543. //展开搜索出来的节点
  544. expandSearchNodes(result);
  545. //设置记住展开
  546. sessionStorage.setItem('stdBillsGuidanceExpState', bills.tree.getExpState(bills.tree.items));
  547. let sel = billsSheet.getSelections();
  548. bills.controller.setTreeSelected(result[0]);
  549. billsSheet.setSelection(result[0].serialNo(), sel[0].col, 1, 1);
  550. billsInitSel(result[0].serialNo());
  551. for (let node of result) {
  552. billsSheet.getRange(node.serialNo(), -1, 1, -1).backColor('lemonChiffon');
  553. }
  554. $('#nextBillsGuidance').show();
  555. $('#nextBillsGuidance').unbind('click');
  556. $('#nextBillsGuidance').bind('click', function () {
  557. let cur = bills.tree.selected, resultIndex = result.indexOf(cur), sel = billsSheet.getSelections();
  558. if (resultIndex === result.length - 1) {
  559. bills.controller.setTreeSelected(result[0]);
  560. billsSheet.setSelection(result[0].serialNo(), sel[0].col, 1, 1);
  561. billsInitSel(result[0].serialNo());
  562. } else {
  563. bills.controller.setTreeSelected(result[resultIndex + 1]);
  564. billsSheet.setSelection(result[resultIndex + 1].serialNo(), sel[0].col, 1, 1);
  565. billsInitSel(result[resultIndex + 1].serialNo());
  566. }
  567. });
  568. } else {
  569. billsLibObj.clearHighLight(bills.workBook);
  570. $('#nextBillsGuidance').hide();
  571. }
  572. $('#billsGuidanceSearchResultCount').text('搜索结果:' + result.length);
  573. $('#billsGuidanceSearchResult').show();
  574. });
  575. // 关闭搜索结果
  576. $('#closeSearchBillsGuidance').click(function () {
  577. $('#billsGuidanceSearchResult').hide();
  578. billsLibObj.clearHighLight(bills.workBook);
  579. refreshWorkBook();
  580. });
  581. }
  582. //刷新表
  583. //@return {void}
  584. function refreshWorkBook(){
  585. if(bills.workBook){
  586. bills.workBook.refresh();
  587. }
  588. if(guideItem.workBook){
  589. guideItem.workBook.refresh();
  590. }
  591. }
  592. return {initViews, bindBtn, refreshWorkBook, bills};
  593. })();
  594. $(document).ready(function(){
  595. billsGuidance.initViews();
  596. billsGuidance.bindBtn();
  597. });