std_billsGuidance_lib.js 49 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171
  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. //更新类型
  13. const updateType = {update: 'update', create: 'create'};
  14. //库类型
  15. const libType = {'guidance': 1, 'elf': 2}; //清单指引、清单精灵
  16. const libSel = $('#stdBillsGuidanceLibSelect');
  17. //工作内容
  18. let stdBillsJobData = [];
  19. //项目特征
  20. let stdBillsFeatureData = [];
  21. //正在插入
  22. let isInserting = false;
  23. const bills = {
  24. dom: $('#billsGuidance_bills'),
  25. workBook: null,
  26. cache: [],
  27. tree: null,
  28. controller: null,
  29. treeSetting: {
  30. emptyRowHeader: true,
  31. rowHeaderWidth: 15,
  32. treeCol: 0,
  33. emptyRows: 0,
  34. headRows: 1,
  35. headRowHeight: [40],
  36. defaultRowHeight: 21,
  37. cols: [{
  38. width: 105,
  39. readOnly: true,
  40. showHint: true,
  41. head: {
  42. titleNames: ["项目编码"],
  43. spanCols: [1],
  44. spanRows: [1],
  45. vAlign: [1],
  46. hAlign: [1],
  47. font: ["Arial"]
  48. },
  49. data: {
  50. field: "code",
  51. vAlign: 1,
  52. hAlign: 0,
  53. font: "Arial"
  54. }
  55. }, {
  56. width: 190,
  57. readOnly: true,
  58. head: {
  59. titleNames: ["项目名称"],
  60. spanCols: [1],
  61. spanRows: [1],
  62. vAlign: [1],
  63. hAlign: [1],
  64. font: ["Arial"]
  65. },
  66. data: {
  67. field: "name",
  68. vAlign: 1,
  69. hAlign: 0,
  70. font: "Arial"
  71. }
  72. },
  73. {
  74. width: 60,
  75. readOnly: true,
  76. head: {
  77. titleNames: ["计量单位"],
  78. spanCols: [1],
  79. spanRows: [1],
  80. vAlign: [1],
  81. hAlign: [1],
  82. font: ["Arial"]
  83. },
  84. data: {
  85. field: "unit",
  86. vAlign: 1,
  87. hAlign: 1,
  88. font: "Arial"
  89. }
  90. }
  91. ]
  92. },
  93. headers: [
  94. {name: '项目编码', dataCode: 'code', width: 105, vAlign: 'center', hAlign: 'left', formatter: '@'},
  95. {name: '项目名称', dataCode: 'name', width: 190, vAlign: 'center', hAlign: 'left', formatter: '@'},
  96. {name: '单位', dataCode: 'unit', width: 60, vAlign: 'center', hAlign: 'center', formatter: '@'},
  97. ],
  98. rowHeaderWidth:1,
  99. events: {
  100. CellDoubleClick: function (sender, args) {
  101. if(!bills.tree){
  102. return;
  103. }
  104. let node = bills.tree.items[args.row];
  105. if(!node){
  106. return;
  107. }
  108. //展开收起(非最底层节点且双击的是第一列)
  109. if (args.col === 0 && node.children.length > 0) {
  110. node.setExpanded(!node.expanded);
  111. //设置展开收起状态
  112. sessionStorage.setItem('stdBillsGuidanceExpState', bills.tree.getExpState(bills.tree.items));
  113. renderSheetFunc(args.sheet, function () {
  114. let iCount = node.posterityCount(), i, child;
  115. for (i = 0; i < iCount; i++) {
  116. child = bills.tree.items[args.row + i + 1];
  117. args.sheet.setRowVisible(args.row + i + 1, child.visible, args.sheetArea);
  118. }
  119. args.sheet.invalidateLayout();
  120. });
  121. args.sheet.repaint();
  122. } else if (!projectReadOnly && !isInserting && !projectObj.project.isBillsLocked() && (args.col !== 0 || node.children.length === 0)) {
  123. //选中部分的最底层(只是选中部分的最底)
  124. let lowestNodes = [bills.tree.items[args.row]];
  125. insertBills(lowestNodes);
  126. }
  127. }
  128. }
  129. };
  130. //插入清单
  131. function insertBills(lowestNodes) {
  132. let selTree = getSelTree(lowestNodes);
  133. let compareData = compareTree(projectObj.project.Bills.tree, selTree);
  134. let sheet = projectObj.mainSpread.getActiveSheet(),
  135. row = sheet.getActiveColumnIndex(),
  136. col = sheet.getActiveColumnIndex();
  137. if (compareData.postData.length > 0) {
  138. //如果插入的是固定清单,则需要判断该固定清单在造价书中是否已存在,造价书中不可存在相同的固定清单
  139. let fixedDatas = compareData.postData.filter((data) =>
  140. data.updateType === updateType.create && Array.isArray(data.updateData.flags));
  141. if (fixedDatas.length > 0) {
  142. //提示已存在此固定清单并且定位
  143. let firstFixed = fixedDatas[0].updateData;
  144. let existNode = projectObj.project.mainTree.items.find((node) =>
  145. node.data && node.data.flagsIndex && node.data.flagsIndex.fixed && node.data.flagsIndex.fixed.flag === firstFixed.flags[0].flag);
  146. if (existNode) {
  147. alert(`固定清单<strong>“${firstFixed.name}”</strong>已被第${existNode.serialNo() + 1}行清单占用。`);
  148. locateAtSpread(sheet, existNode.serialNo(), col);
  149. return;
  150. }
  151. }
  152. isInserting = true;
  153. CommonAjax.post('/bills/insertBills', {postData: compareData.postData}, function () {
  154. //插入
  155. let insertData = _.filter(compareData.postData, {updateType: updateType.create});
  156. let treeData = [];
  157. for (let data of insertData) {
  158. treeData.push(data.updateData);
  159. }
  160. //插入清单节点
  161. projectObj.project.Bills.tree.insertByDatas(treeData);
  162. projectObj.project.Bills.datas = projectObj.project.Bills.datas.concat(treeData);
  163. //插入主树节点
  164. let newNodes = projectObj.project.mainTree.insertByDatas(treeData);
  165. for (let node of newNodes) {
  166. node.source = projectObj.project.Bills.tree.nodes[projectObj.project.Bills.tree.prefix + node.getID()];
  167. node.data = node.source.data;
  168. node.sourceType = projectObj.project.Bills.getSourceType();
  169. }
  170. ProjectController.syncDisplayNewNodes(projectObj.mainController, newNodes, true);
  171. row = newNodes[newNodes.length - 1].serialNo();
  172. //有新的节点插入,也有可能定位至旧节点(批量选用的情况下)
  173. if (compareData.locateNode) {
  174. //该清单节点在主树的位置
  175. row = projectObj.project.mainTree.nodes[projectObj.project.mainTree.prefix + compareData.locateNode.data.ID].serialNo();
  176. }
  177. locateAtSpread(sheet, row, col);
  178. isInserting = false;
  179. }, function () {
  180. isInserting = false;
  181. });
  182. } else if (compareData.locateNode) {
  183. //该清单节点在主树的位置
  184. row = projectObj.project.mainTree.nodes[projectObj.project.mainTree.prefix + compareData.locateNode.data.ID].serialNo();
  185. locateAtSpread(sheet, row, col);
  186. }
  187. }
  188. function locateAtSpread(sheet, row, col) {
  189. sheet.setSelection(row, col, 1, 1);
  190. projectObj.mainController.setTreeSelected(projectObj.mainController.tree.items[row]);//触发树节点选中事件
  191. sheet.showRow(row, GC.Spread.Sheets.VerticalPosition.center);
  192. }
  193. /*
  194. *
  195. * 1.选中的树结构(清单规则选中的节点及其所有父项)与主树对比(主树中节点“编码-名称-单位”与选中树~组合相同视为同一节点),
  196. * 将主树中不含有的选中节点全部插入
  197. * 2.插入位置由1对比得出,主树有与选中树结构相同层次结构的片段,这个相同片段为插入位置
  198. * 3.选中树结构除去相同片段,为需要插入的节点,插入时,遇到同层节点,根据编码的字符编码值确定顺序
  199. * a.code <= b.code,则a节点在b节点前
  200. * */
  201. //获取选中的树(将选中的节点及其所有父项,组合成一棵树,没有重复节点)
  202. //@param {Array}lowestNodes(选中的最底层节点) @return {Array}
  203. function getSelTree(lowestNodes) {
  204. let allNodes = [];
  205. //获取树上所有的节点
  206. for (let node of lowestNodes) {
  207. while (node && !allNodes.includes(node)) {
  208. allNodes.push(node);
  209. node = node.parent;
  210. }
  211. }
  212. //根据原节点serialNo排序,排序后,后一项节点只可能前节点的后兄弟项,或子项(根据原节点ID-ParentID判定)
  213. allNodes.sort(function (a, b) {
  214. let aV = a.serialNo(),
  215. bV = b.serialNo();
  216. if (aV > bV) {
  217. return 1;
  218. } else if (aV < bV) {
  219. return -1;
  220. }
  221. return 0;
  222. });
  223. //生成树数据
  224. let treeData = [];
  225. //旧ID与新ID映射
  226. let IDMapping = {};
  227. for (let i = 0; i < allNodes.length; i++) {
  228. //原节点
  229. let preN = allNodes[i - 1],
  230. thisN = allNodes[i];
  231. let newNodeData = {ID: uuid.v1(), NextSiblingID: -1, ParentID: -1, orgID: thisN.data.ID};
  232. IDMapping[newNodeData.orgID] = newNodeData.ID;
  233. treeData.push(newNodeData);
  234. //新树数据
  235. let preData = treeData[i - 1],
  236. thisData = treeData[i];
  237. //节点与上节点为同层节点,则此节点设为上节点的后兄弟
  238. if (preN && preN.data.ParentID === thisN.data.ParentID) {
  239. preData.NextSiblingID = thisData.ID;
  240. //节点与上节点不为同层节点,则此节点为某上节点的子几点
  241. } else if (preN && preN.data.ParentID !== thisN.data.ParentID) {
  242. let parentID = IDMapping[thisN.data.ParentID];
  243. thisData.ParentID = parentID;
  244. }
  245. }
  246. let selTree = idTree.createNew({id: 'ID', pid: 'ParentID', nid: 'NextSiblingID', rootId: -1, autoUpdate: true});
  247. selTree.loadDatas(treeData);
  248. return selTree;
  249. }
  250. /*
  251. * 选中树与清单主树进行对比,(自上而下,从roots开始)获取插入、更新数据
  252. * 找到的清单树中清单子项含有非清单项或输入了计算基数,则中止该清单的对比,不可插入数据
  253. * */
  254. //获取节点的匹配数据:编码-名称-单位
  255. //@param {Object}node @return {String}
  256. function getMatchContent(node) {
  257. return `${node.data.code ? node.data.code : '*'}-${node.data.name ? node.data.name : '*'}-${node.data.unit ? node.data.unit: '*'}`;
  258. }
  259. //**对比清单主树与选中树,获取需要更新和插入的数据**
  260. //@param {Object}mainTree {Object}selTree
  261. function compareTree(billsTree, selTree) {
  262. //需要插入、更新的数据
  263. let postData = [],
  264. //跟树结构自动定位至的清单节点(最近匹配到的节点)
  265. locateNode = null;
  266. if (!billsTree || !selTree) {
  267. return postData;
  268. }
  269. comparePeer(null, billsTree.roots, selTree.roots);
  270. return {postData, locateNode};
  271. /*
  272. * 该清单节点是否可以继续往下递归匹配,即该节点是否还可插入子项(在该层匹配到的时候判断)
  273. * 1.该底层节点不能含有非清单子项
  274. * 2.该节点不能含有计算基数
  275. * todo 3.数量单价等相关概念,等有了补上
  276. * @param {Object}billsNode(清单树中的某节点) @return {Boolean}
  277. * */
  278. function canRecursive(billsNode) {
  279. //主树节点含有子节点,清单节点不含子节点,说明该节点含有非清单子项
  280. //这里需要去mainTree查,不能在清单树查,因为清单树的节点children里只会有清单,就算实际上有定额,这个children里也不含该定额
  281. let mainTreeNode = projectObj.project.mainTree.getNodeByID(billsNode.data.ID);
  282. if (!mainTreeNode) {
  283. return false;
  284. }
  285. if (mainTreeNode && mainTreeNode.children.length > 0 && billsNode.children.length === 0) {
  286. return false;
  287. } else if (billsNode.data.calcBase) {
  288. return false;
  289. }
  290. return true;
  291. }
  292. //获取某选中节点要往清单主树同层插入的位置
  293. function insertPos(peerNodes, node) {
  294. //node选中树中没有记录原清单的数据,只记录了原清单ID,需要node的数据,则要找回原清单
  295. let orgNode = bills.tree.nodes[`${bills.tree.prefix}${node.data.orgID}`];
  296. if (!orgNode) {
  297. return -1;
  298. }
  299. let insertCode = orgNode.data.code ? orgNode.data.code : '';
  300. //插入最顶层节点或者无编码,对比选中节点后兄弟节点和同层主树节点的名称,插在的匹配的节点前面
  301. function mathNext(selNode, compareNodes) {
  302. let selNext = selNode.nextSibling;
  303. while (selNext) {
  304. for (let i = 0; i < compareNodes.length; i++) {
  305. if (compareNodes[i].data.name === selNext.data.name) {
  306. return i;
  307. }
  308. }
  309. selNext = selNext.nextSibling;
  310. }
  311. return compareNodes.length;
  312. }
  313. if (orgNode.depth() === 0 || insertCode === '') {
  314. return mathNext(orgNode, peerNodes);
  315. //return peerNodes.length;
  316. }
  317. for (let i = 0; i < peerNodes.length; i++) {
  318. let thisNode = peerNodes[i];
  319. let thisCode = thisNode.data.code ? thisNode.data.code : '';
  320. //确定同层节点的顺序,编码小于等于在前,大于在后
  321. if (insertCode <= thisCode) {
  322. return i;
  323. } else if (insertCode > thisCode) {
  324. continue;
  325. }
  326. }
  327. return peerNodes.length;
  328. }
  329. //获取插入清单数据
  330. function getInsertData(insertObj) {
  331. let stdNode = bills.tree.nodes[`${bills.tree.prefix}${insertObj.orgID}`];
  332. if (!stdNode) {
  333. return null;
  334. }
  335. let stdData = {};
  336. stdData.projectID = projectObj.project.projectInfo.ID;
  337. stdData.isAdd = 1;
  338. stdData.ID = insertObj.ID;
  339. stdData.ParentID = insertObj.ParentID;
  340. stdData.NextSiblingID = insertObj.NextSiblingID;
  341. //顶层节点是大项费用
  342. stdData.type = stdNode.parent ? billType.BILL : billType.DXFY;
  343. stdData.code = stdNode.data.code;
  344. stdData.name = stdNode.data.name;
  345. stdData.unit = stdNode.data.unit;
  346. stdData.ruleText = stdNode.data.ruleText;
  347. stdData.comments = stdNode.data.comments;
  348. stdData.programID = stdNode.data.engineering;
  349. stdData.billsLibId = stdNode.data.billsLibId;
  350. if (stdNode.data.fixedFlag) {
  351. stdData.flags = [{flag : stdNode.data.fixedFlag, fieldName : 'fixed'}];
  352. stdData.flagsIndex = {fixed: {fieldName: 'fixed', flag: stdNode.data.fixedFlag}}; //前端用
  353. }
  354. return stdData;
  355. }
  356. //从同层节点中获取更新数据
  357. //@param {Object}parentNode(同层节点挂载的父节点,清单主树中) {Array}peerNodes(同层节点,含有清单树和选中树节点)
  358. // {Array}billsNodes(该层清单树节点) {Array}selNodes(该层选中树节点) @return {Array}
  359. function getUpdateDataFromPeer(parentNode, peerNodes, billsNodes, selNodes) {
  360. let rst = [];
  361. //向下获取插入数据直到最底层
  362. function getDataTillDeepest(node) {
  363. if (node) {
  364. let insertData = getInsertData(node.data);
  365. if (insertData) {
  366. rst.push({updateType: updateType.create, updateData: insertData});
  367. }
  368. for (let child of node.children) {
  369. getDataTillDeepest(child);
  370. }
  371. }
  372. }
  373. for (let i = 0; i < peerNodes.length; i++) {
  374. let thisNode = peerNodes[i],
  375. nextNode = peerNodes[i + 1];
  376. //更新原清单节点NextSiblingID
  377. if (billsNodes.includes(thisNode) && selNodes.includes(nextNode)) {
  378. rst.push({updateType: updateType.update, updateData: {ID: thisNode.data.ID, NextSiblingID: nextNode.data.ID}});
  379. } else if (selNodes.includes(thisNode) && billsNodes.includes(nextNode)) { //变更选中节点的NextSiblingID
  380. thisNode.data.NextSiblingID = nextNode.data.ID;
  381. }
  382. //所有选中的同层节点设为清单树父节点的子项,获取插入数据(插入该同层节点及其所有子节点)
  383. if (selNodes.includes(thisNode)) {
  384. thisNode.data.ParentID = parentNode ? parentNode.data.ID : -1;
  385. getDataTillDeepest(thisNode);
  386. }
  387. }
  388. return rst;
  389. }
  390. //同层节点之间比较,匹配到的则继续往下匹配,匹配不到的节点则按照规定的顺序进行排序,插入更新(更新清单树节点中NextSiblingID改变的节点)
  391. function comparePeer(parentNode, billsNodes, selNodes) {
  392. let peerNodes = [].concat(billsNodes); //同层节点
  393. let matchNode = null; //匹配到的清单主树节点
  394. for (let selNode of selNodes) {
  395. let stdNode = bills.tree.nodes[`${bills.tree.prefix}${selNode.data.orgID}`],
  396. selMatch = getMatchContent(stdNode),
  397. isMatched = false;
  398. for( let billsNode of billsNodes) {
  399. let billsMatch = getMatchContent(billsNode);
  400. if (selMatch === billsMatch) {//只进行一次成功匹配
  401. matchNode = billsNode;
  402. isMatched = true;
  403. if (selNode.children.length === 0) {//成功匹配且为选中的最底节点,则为自动定位节点
  404. locateNode = matchNode;
  405. }
  406. break;
  407. }
  408. }
  409. if (isMatched && canRecursive(matchNode)) {//匹配成功,且该匹配到的节点可插入子项,递归匹配子项
  410. comparePeer(matchNode, matchNode.children, selNode.children);
  411. } else if (!isMatched) { //匹配不成功,其节点与该层清单节点同层,根据编码插入同层数组中
  412. let pos = insertPos(peerNodes, selNode);
  413. if (pos >= 0) {
  414. peerNodes.splice(pos, 0, selNode);
  415. }
  416. }
  417. }
  418. //同层节点比清单树节点多了,说明在该层有选中节点插入清单树中
  419. if (peerNodes.length > billsNodes.length) {
  420. let updateData = getUpdateDataFromPeer(parentNode, peerNodes, billsNodes, selNodes);
  421. postData = postData.concat(updateData);
  422. }
  423. }
  424. }
  425. //项目指引类型
  426. const itemType = {
  427. job: 0,
  428. ration: 1
  429. };
  430. const guideItem = {
  431. dom: $('#billsGuidance_items'),
  432. workBook: null,
  433. tree: null,
  434. controller: null,
  435. treeSetting: {
  436. treeCol: 1,
  437. emptyRows: 0,
  438. headRows: 1,
  439. headRowHeight: [40],
  440. defaultRowHeight: 21,
  441. cols: [
  442. {
  443. width: 35,
  444. readOnly: false,
  445. head: {
  446. titleNames: ["选择"],
  447. spanCols: [1],
  448. spanRows: [1],
  449. vAlign: [1],
  450. hAlign: [1],
  451. font: ["Arial"]
  452. },
  453. data: {
  454. field: "select",
  455. vAlign: 1,
  456. hAlign: 1,
  457. font: "Arial"
  458. }
  459. },
  460. {
  461. width: 420,
  462. readOnly: false,
  463. head: {
  464. titleNames: ["项目指引"],
  465. spanCols: [1],
  466. spanRows: [1],
  467. vAlign: [1],
  468. hAlign: [1],
  469. font: ["Arial"]
  470. },
  471. data: {
  472. field: "name",
  473. vAlign: 1,
  474. hAlign: 0,
  475. font: "Arial"
  476. }
  477. }
  478. ]
  479. },
  480. headers: [
  481. {name: '选择', dataCode: 'select', width: 35, vAlign: 'center', hAlign: 'center', formatter: '@'},
  482. {name: '项目指引', dataCode: 'name', width: 300, vAlign: 'center', hAlign: 'left', formatter: '@'},
  483. ],
  484. rowHeaderWidth:25,
  485. events: {
  486. EditStarting: function (sender, args) {
  487. if(!bills.tree || guideItem.headers[args.col]['dataCode'] === 'name'){
  488. args.cancel = true;
  489. }
  490. },
  491. ButtonClicked: function (sender, args) {
  492. if(args.sheet.isEditing()){
  493. args.sheet.endEdit(true);
  494. }
  495. refreshInsertRation();
  496. },
  497. CellDoubleClick: function (sender, args) {
  498. if(!bills.tree || !bills.tree.selected){
  499. return;
  500. }
  501. let node = bills.tree.selected.guidance.tree.selected;
  502. if(!node){
  503. return;
  504. }
  505. if(node.children.length === 0){
  506. if(guideItem.headers[args.col]['dataCode'] === 'name'){
  507. insertRations(getInsertRationData([args.row]));
  508. }
  509. }
  510. else {
  511. node.setExpanded(!node.expanded);
  512. renderSheetFunc(args.sheet, function () {
  513. let iCount = node.posterityCount(), i, child;
  514. for (i = 0; i < iCount; i++) {
  515. child = bills.tree.selected.guidance.tree.items[args.row + i + 1];
  516. args.sheet.setRowVisible(args.row + i + 1, child.visible, args.sheetArea);
  517. }
  518. args.sheet.invalidateLayout();
  519. });
  520. args.sheet.repaint();
  521. }
  522. }
  523. }
  524. };
  525. const elfItem = {
  526. dom: $('#billsGuidance_items'),
  527. workBook: null,
  528. tree: null,
  529. controller: null,
  530. treeSetting: {
  531. treeCol: 0,
  532. emptyRows: 0,
  533. headRows: 1,
  534. headRowHeight: [40],
  535. defaultRowHeight: 21,
  536. cols: [
  537. {
  538. width: 250,
  539. readOnly: true,
  540. head: {
  541. titleNames: ["施工工序"],
  542. spanCols: [1],
  543. spanRows: [1],
  544. vAlign: [1],
  545. hAlign: [1],
  546. font: ["Arial"]
  547. },
  548. data: {
  549. field: "name",
  550. vAlign: 1,
  551. hAlign: 0,
  552. font: "Arial"
  553. }
  554. },
  555. {
  556. width: 250,
  557. readOnly: false,
  558. head: {
  559. titleNames: ["选项"],
  560. spanCols: [1],
  561. spanRows: [1],
  562. vAlign: [1],
  563. hAlign: [1],
  564. font: ["Arial"]
  565. },
  566. data: {
  567. field: "options",
  568. vAlign: 1,
  569. hAlign: 0,
  570. font: "Arial"
  571. }
  572. }
  573. ]
  574. },
  575. headers: [
  576. {name: '施工工序', dataCode: 'name', width: 250, rateWidth: 0.5, vAlign: 'center', hAlign: 'center', formatter: '@'},
  577. {name: '选项', dataCode: 'options', width: 250, rateWidth: 0.5, vAlign: 'center', hAlign: 'left', formatter: '@'},
  578. ],
  579. rowHeaderWidth:25,
  580. events: {
  581. CellClick: function (sender, args) {
  582. if(elfItem.headers[args.col]['dataCode'] === 'options' && args.sheetArea === 3){
  583. if(!args.sheet.getCell(args.row, args.col).locked() && !args.sheet.isEditing()){
  584. args.sheet.startEdit();
  585. }
  586. }
  587. },
  588. ClipboardPasting: function (sender, info) {
  589. info.cancel = true;
  590. }
  591. }
  592. };
  593. const options = {
  594. workBook: {
  595. tabStripVisible: false,
  596. allowContextMenu: false,
  597. allowCopyPasteExcelStyle : false,
  598. allowExtendPasteRange: false,
  599. allowUserDragDrop : false,
  600. allowUserDragFill: false,
  601. scrollbarMaxAlign : true
  602. },
  603. sheet: {
  604. protectionOptions: {allowResizeRows: true, allowResizeColumns: true},
  605. clipBoardOptions: GC.Spread.Sheets.ClipboardPasteOptions.values
  606. }
  607. };
  608. //渲染时方法,停止渲染
  609. //@param {Object}sheet {Function}func @return {void}
  610. function renderSheetFunc(sheet, func){
  611. sheet.suspendEvent();
  612. sheet.suspendPaint();
  613. if(func){
  614. func();
  615. }
  616. sheet.resumeEvent();
  617. sheet.resumePaint();
  618. }
  619. //设置表选项
  620. //@param {Object}workBook {Object}opts @return {void}
  621. function setOptions (workBook, opts) {
  622. for(let opt in opts.workBook){
  623. workBook.options[opt] = opts.workBook[opt];
  624. }
  625. for(let opt in opts.sheet){
  626. workBook.getActiveSheet().options[opt] = opts.sheet[opt];
  627. }
  628. }
  629. //建表头
  630. //@param {Object}sheet {Array}headers @return {void}
  631. function buildHeader(sheet, headers) {
  632. let fuc = function () {
  633. sheet.setColumnCount(headers.length);
  634. sheet.setRowHeight(0, 30, GC.Spread.Sheets.SheetArea.colHeader);
  635. //sheet.setColumnWidth(0, sheet.getParent() === bills.workBook ? 15 : 25, GC.Spread.Sheets.SheetArea.rowHeader);
  636. if(sheet.getParent() === elfItem.workBook || sheet.getParent() === guideItem.workBook){
  637. sheet.setRowHeight(0, 20, GC.Spread.Sheets.SheetArea.colHeader);
  638. }
  639. for(let i = 0, len = headers.length; i < len; i++){
  640. sheet.setValue(0, i, headers[i].name, GC.Spread.Sheets.SheetArea.colHeader);
  641. sheet.setColumnWidth(i, headers[i].width, GC.Spread.Sheets.SheetArea.colHeader);
  642. if(headers[i].formatter){
  643. sheet.setFormatter(-1, i, headers[i].formatter);
  644. }
  645. sheet.getRange(-1, i, -1, 1).hAlign(GC.Spread.Sheets.HorizontalAlign[headers[i]['hAlign']]);
  646. sheet.getRange(-1, i, -1, 1).vAlign(GC.Spread.Sheets.VerticalAlign[headers[i]['vAlign']]);
  647. }
  648. };
  649. renderSheetFunc(sheet, fuc);
  650. }
  651. //表监听事件
  652. //@param {Object}workBook @return {void}
  653. function bindEvent(workBook, events) {
  654. if(Object.keys(events).length === 0){
  655. return;
  656. }
  657. const Events = GC.Spread.Sheets.Events;
  658. for(let event in events){
  659. workBook.bind(Events[event], events[event]);
  660. }
  661. }
  662. //根据宽度比例设置列宽
  663. //@param {Object}workBook {Number}workBookWidth {Array}headers @return {void}
  664. function setColumnWidthByRate(workBook, workBookWidth, headers) {
  665. if(workBook){
  666. workBookWidth -= 48;
  667. const sheet = workBook.getActiveSheet();
  668. sheet.suspendEvent();
  669. sheet.suspendPaint();
  670. for(let col = 0; col < headers.length; col++){
  671. if(headers[col]['rateWidth'] !== undefined && headers[col]['rateWidth'] !== null && headers[col]['rateWidth'] !== ''){
  672. let width = workBookWidth * headers[col]['rateWidth'];
  673. if(headers[col]['dataCode'] === 'options'){
  674. width = width;
  675. }
  676. sheet.setColumnWidth(col, width, GC.Spread.Sheets.SheetArea.colHeader)
  677. }
  678. else {
  679. if(headers[col]['headerWidth'] !== undefined && headers[col]['headerWidth'] !== null && headers[col]['headerWidth'] !== ''){
  680. sheet.setColumnWidth(col, headers[col]['headerWidth'], GC.Spread.Sheets.SheetArea.colHeader)
  681. }
  682. }
  683. }
  684. sheet.resumeEvent();
  685. sheet.resumePaint();
  686. }
  687. }
  688. //建表
  689. //@param {Object}module @return {void}
  690. function buildSheet(module) {
  691. if(!module.workBook){
  692. module.workBook = new GC.Spread.Sheets.Workbook(module.dom[0], {sheetCount: 1});
  693. sheetCommonObj.spreadDefaultStyle(module.workBook);
  694. let sheet = module.workBook.getActiveSheet();
  695. if(module === bills){
  696. //默认初始可控制焦点在清单表中
  697. sheet.options.rowHeaderVisible = false;
  698. module.workBook.focus();
  699. sheet.options.isProtected = true;
  700. sheet.name('stdBillsGuidance_bills');
  701. //设置悬浮提示
  702. TREE_SHEET_HELPER.initSetting(bills.dom[0], bills.treeSetting);
  703. }
  704. if(module === guideItem){
  705. sheet.options.isProtected = true;
  706. sheet.getRange(-1, 0, -1, 1).locked(false);
  707. sheet.getRange(-1, 1, -1, 1).locked(true);
  708. }
  709. if(module === elfItem){
  710. sheet.options.isProtected = true;
  711. sheet.getRange(-1, 0, -1, 1).locked(true);
  712. sheet.getRange(-1, 1, -1, 1).locked(false);
  713. }
  714. if(module.rowHeaderWidth) {
  715. sheet.setColumnWidth(0, module.rowHeaderWidth, GC.Spread.Sheets.SheetArea.rowHeader);
  716. }
  717. setOptions(module.workBook, options);
  718. buildHeader(module.workBook.getActiveSheet(), module.headers);
  719. if(module === elfItem){
  720. setColumnWidthByRate(elfItem.workBook, $('#zy').width(), elfItem.headers)
  721. }
  722. bindEvent(module.workBook, module.events);
  723. }
  724. }
  725. //清空表数据
  726. //@param {Object}sheet {Array}headers {Number}rowCount @return {void}
  727. function cleanData(sheet, headers, rowCount){
  728. renderSheetFunc(sheet, function () {
  729. sheet.clear(-1, 0, -1, headers.length, GC.Spread.Sheets.SheetArea.viewport, GC.Spread.Sheets.StorageType.data);
  730. if (rowCount > 0) {
  731. sheet.setRowCount(rowCount);
  732. }
  733. });
  734. }
  735. //初始化各工作表
  736. //@param {Array}modules @return {void}
  737. function initWorkBooks(modules){
  738. for(let module of modules){
  739. buildSheet(module);
  740. }
  741. }
  742. //点击清单名称后面的问号,弹出补注窗口并设置当前节点(或xxx父节点)的补注
  743. //@param {Number}row(当前焦点行) @return {void}
  744. function initRechargeModal(row) {
  745. let node = bills.tree.items[row];
  746. while (node && !node.data.recharge){
  747. node = node.parent;
  748. }
  749. let recharge = node && node.data.recharge ? node.data.recharge : '无内容';
  750. node = bills.tree.items[row];
  751. while (node && !node.data.ruleText){
  752. node = node.parent;
  753. }
  754. let ruleText = node && node.data.ruleText ? node.data.ruleText : '无内容';
  755. $('#questionTab1').text('补注');
  756. $('#questionTab2').text('工程量计算规则');
  757. $('#questionContent1').html(recharge);
  758. $('#questionContent2').html(ruleText);
  759. $('#questionModal').modal('show');
  760. }
  761. //节点链上含有补注或工程量计算规则数据
  762. //@param {Number}row(行当前行) @return {Boolean}
  763. function hasRechargeRuleText(row) {
  764. let node = bills.tree.items[row];
  765. if (!node) {
  766. return false;
  767. }
  768. while (node) {
  769. if (node.data.recharge || node.data.ruleText) {
  770. return true;
  771. }
  772. node = node.parent;
  773. }
  774. return false;
  775. }
  776. //初始化并输出树
  777. //@param {Object}module {Object}sheet {Object}treeSetting {Array}datas
  778. function initTree(module, sheet, treeSetting, datas){
  779. module.tree = idTree.createNew({id: 'ID', pid: 'ParentID', nid: 'NextSiblingID', rootId: -1, autoUpdate: true});
  780. module.controller = TREE_SHEET_CONTROLLER.createNew(module.tree, sheet, treeSetting, false);
  781. module.tree.loadDatas(datas);
  782. if(module === bills){
  783. initExpandStat();
  784. }
  785. module.controller.showTreeData();
  786. if(module === bills){
  787. module.workBook.getSheet(0).options.rowHeaderVisible = true;
  788. setBillsHint(bills.tree.items, stdBillsJobData, stdBillsFeatureData);
  789. renderSheetFunc(sheet, function () {
  790. for(let i = 0; i < bills.tree.items.length; i++){
  791. sheet.setCellType(i, 1, TREE_SHEET_HELPER.getQuestionCellType(initRechargeModal, hasRechargeRuleText));
  792. }
  793. });
  794. }
  795. }
  796. //项目指引表焦点控制
  797. //@param {Number}row @return {void}
  798. function guideItemInitSel(row){
  799. let billsNode = bills.tree.selected;
  800. let node = null;
  801. if(billsNode && billsNode.guidance.tree){
  802. node = billsNode.guidance.tree.items[row];
  803. if(node){
  804. billsNode.guidance.tree.selected = node;
  805. }
  806. }
  807. }
  808. //清单精灵表焦点控制
  809. //@param {Number}row @return {void}
  810. function elfItemInitSel(row){
  811. let billsNode = bills.tree.selected;
  812. let node = null;
  813. if(billsNode && billsNode.elf.tree){
  814. node = billsNode.elf.tree.items[row];
  815. if(node){
  816. billsNode.elf.tree.selected = node;
  817. }
  818. }
  819. }
  820. //根据项目指引的类型设置单元格类型,定额类型的项目指引为复选框
  821. //@param {Array}nodes @return {void}
  822. function setItemCellType(nodes){
  823. //设置单元格类型
  824. const base = new GC.Spread.Sheets.CellTypes.Base();
  825. const checkBox = new GC.Spread.Sheets.CellTypes.CheckBox();
  826. const sheet = guideItem.workBook.getActiveSheet();
  827. renderSheetFunc(sheet, function(){
  828. for(let node of nodes){
  829. sheet.setCellType(node.serialNo(), 0, node.data.type === itemType.ration ? checkBox : base);
  830. }
  831. });
  832. }
  833. //初始化清单的工作内容和项目特征
  834. //@param {Number}billsLibId {Function}callback @return {void}
  835. function initJobAndCharacter(billsLibId, callback){
  836. CommonAjax.post('/stdBillsEditor/getJobContent', {userId: userID, billsLibId: billsLibId}, function (datas) {
  837. stdBillsJobData = datas;
  838. CommonAjax.post('/stdBillsEditor/getItemCharacter', {userId: userID, billsLibId: billsLibId}, function (datas) {
  839. stdBillsFeatureData = datas;
  840. if(callback){
  841. callback();
  842. }
  843. });
  844. });
  845. }
  846. //初始化清单展开收起状态
  847. //@return {void}
  848. function initExpandStat(){
  849. //读取展开收起状态
  850. let currentExpState = sessionStorage.getItem('stdBillsGuidanceExpState');
  851. if(currentExpState){
  852. bills.tree.setExpandedByState(bills.tree.items, currentExpState);
  853. }
  854. //非叶子节点默认收起
  855. else{
  856. bills.tree.setRootExpanded(bills.tree.roots, false);
  857. }
  858. }
  859. //设置tag以悬浮提示
  860. function setTagForHint(nodes){
  861. let sheet = bills.workBook.getActiveSheet();
  862. renderSheetFunc(sheet, function () {
  863. for(let node of nodes){
  864. sheet.setTag(node.serialNo(), 2, node.data.ruleText ? node.data.ruleText : '');
  865. }
  866. });
  867. }
  868. //根据编码定位至清单精灵库中
  869. //@param {String}code @return {void}
  870. function locateAtBills(code) {
  871. let nineCode = code.substring(0, 9);
  872. let items = bills.tree.items;
  873. let locateBills = _.find(items, function(item){
  874. return item.data.code === nineCode;
  875. });
  876. if(locateBills){
  877. expandSearchNodes([locateBills]);
  878. sessionStorage.setItem('stdBillsGuidanceExpState', bills.tree.getExpState(bills.tree.items));
  879. }
  880. let sheet = bills.workBook.getActiveSheet();
  881. let locateRow = locateBills ? locateBills.serialNo() : 0;
  882. sheet.setActiveCell(locateRow, 0);
  883. sheet.showRow(locateRow, GC.Spread.Sheets.VerticalPosition.center);
  884. }
  885. //清单设置悬浮提示信息
  886. //@param {Array}billsNodes(清单节点) {Array}jobs(总的工作内容数据) {Array}items(总的项目特征数据)
  887. function setBillsHint(billsNodes, jobs, items) {
  888. let jobsMapping = {},
  889. itemsMapping = {};
  890. for(let job of jobs){
  891. jobsMapping[job.id] = job;
  892. }
  893. for(let item of items){
  894. itemsMapping[item.id] = item;
  895. }
  896. let tagInfo = [];
  897. for(let billsNode of billsNodes){
  898. let hintArr = [];
  899. let billsItems = billsNode.data.items;
  900. if(billsItems.length > 0){
  901. //项目特征
  902. hintArr.push('项目特征:');
  903. }
  904. let itemCount = 1,
  905. jobCount = 1;
  906. for(let billsItem of billsItems){
  907. let itemData = itemsMapping[billsItem.id];
  908. if(itemData){
  909. //特征值
  910. let eigens = [];
  911. for(let eigen of itemData.itemValue){
  912. eigens.push(eigen.value);
  913. }
  914. eigens = eigens.join(';');
  915. hintArr.push(`${itemCount}.${itemData.content}${eigens === '' ? '' : ': ' + eigens}`);
  916. itemCount ++;
  917. }
  918. }
  919. //工作内容
  920. let billsJobs = billsNode.data.jobs;
  921. if(billsJobs.length > 0){
  922. hintArr.push('工作内容:');
  923. }
  924. for(let billsJob of billsJobs){
  925. let jobData = jobsMapping[billsJob.id];
  926. if(jobData){
  927. hintArr.push(`${jobCount}.${jobData.content}`);
  928. jobCount ++;
  929. }
  930. }
  931. /*if(billsNode.data.ruleText && billsNode.data.ruleText !== ''){
  932. hintArr.push('工程量计算规则:');
  933. hintArr.push(billsNode.data.ruleText);
  934. }
  935. if(billsNode.data.recharge && billsNode.data.recharge !== ''){
  936. hintArr.push('补注:');
  937. hintArr.push(billsNode.data.recharge);
  938. }*/
  939. if(hintArr.length > 0){
  940. tagInfo.push({row: billsNode.serialNo(), value: hintArr.join('\n')});
  941. }
  942. }
  943. let sheet = bills.workBook.getActiveSheet();
  944. renderSheetFunc(sheet, function () {
  945. for(let tagI of tagInfo){
  946. sheet.setTag(tagI.row, 0, tagI.value);
  947. }
  948. });
  949. }
  950. //初始选择标准清单
  951. //@param {Number}libID @return {void}
  952. function libInitSel(libID){
  953. //获取清单
  954. $.bootstrapLoading.start();
  955. CommonAjax.post('/billsGuidance/api/getLibWithBills', {libID: libID}, function(rstData){
  956. if(guideItem.workBook){
  957. guideItem.workBook.destroy();
  958. guideItem.workBook = null;
  959. }
  960. if(elfItem.workBook){
  961. elfItem.workBook.destroy();
  962. elfItem.workBook = null;
  963. }
  964. initViews();
  965. initTree(bills, bills.workBook.getActiveSheet(), bills.treeSetting, rstData.bills);
  966. let callback = function () {
  967. if(doAfterLoadGuidance){
  968. doAfterLoadGuidance();
  969. }
  970. $.bootstrapLoading.end();
  971. };
  972. //获取清单库中的工作内容和项目特征
  973. initJobAndCharacter(libID, callback);
  974. }, function () {
  975. $.bootstrapLoading.end();
  976. });
  977. }
  978. //初始化清单指引库
  979. //@param {Array}libDats @return {void}
  980. function initLibs(libDatas){
  981. libSel.empty();
  982. if(!libDatas){
  983. return;
  984. }
  985. let selectedLib = sessionStorage.getItem('stdBillsGuidance');
  986. for(let libData of libDatas){
  987. let opt = $('<option>').val(libData.id).text(libData.name);
  988. if(selectedLib && libData.id == selectedLib){
  989. opt.attr('selected', 'selected');
  990. }
  991. libSel.append(opt);
  992. }
  993. //初始默认选择
  994. libInitSel(libSel.select().val());
  995. }
  996. //初始化视图
  997. //@param {void} @return {void}
  998. function initViews(){
  999. //赋初始高度
  1000. if($('#billsGuidance_bills').height() === 0 || $('#billsGuidance_items').height() === 0){
  1001. let height = $(window).height()-$(".header").height()-$(".toolsbar").height()-$(".tools-bar-height-z").height();
  1002. $('#billsGuidance_bills').height(height / 2);
  1003. $('#billsGuidance_items').height(height / 2);
  1004. }
  1005. let modules = [bills];
  1006. modules.push(elfItem);
  1007. initWorkBooks(modules);
  1008. }
  1009. //展开至搜索出来点的节点
  1010. //@param {Array}nodes @return {void}
  1011. function expandSearchNodes(nodes){
  1012. let that = this;
  1013. let billsSheet = bills.workBook.getActiveSheet();
  1014. renderSheetFunc(billsSheet, function () {
  1015. function expParentNode(node){
  1016. if(node.parent){
  1017. if (!node.parent.expanded) {
  1018. node.parent.setExpanded(true);
  1019. }
  1020. expParentNode(node.parent);
  1021. }
  1022. }
  1023. for(let node of nodes){
  1024. expParentNode(node);
  1025. }
  1026. TREE_SHEET_HELPER.refreshTreeNodeData(bills.treeSetting, billsSheet, bills.tree.roots, true);
  1027. TREE_SHEET_HELPER.refreshNodesVisible(bills.tree.roots, billsSheet, true);
  1028. });
  1029. }
  1030. //各按钮监听事件
  1031. //@return {void}
  1032. function bindBtn(){
  1033. //打开清单指引库
  1034. $('#stdBillsGuidanceTab').click(function () {
  1035. if(libSel.children().length === 0 && !$(this).hasClass('disabled')){
  1036. initLibs(projectObj.project.projectInfo.engineeringInfo.bill_lib);
  1037. }
  1038. });
  1039. //更改清单指引库
  1040. $('#stdBillsGuidanceLibSelect').change(function () {
  1041. //关闭搜索窗口
  1042. $('#billsGuidanceSearchResult').hide();
  1043. billsLibObj.clearHighLight(bills.workBook);
  1044. libInitSel($(this).select().val());
  1045. //记住选项
  1046. sessionStorage.setItem('stdBillsGuidance', $(this).select().val());
  1047. //清除展开收起状态sessionStorage
  1048. sessionStorage.removeItem('stdBillsGuidanceExpState');
  1049. });
  1050. //搜索
  1051. $('#stdBillsGuidanceSearch>div>button').click(function () {
  1052. if(!bills.tree){
  1053. return;
  1054. }
  1055. let billsSheet = bills.workBook.getActiveSheet();
  1056. billsLibObj.clearHighLight(bills.workBook);
  1057. let keyword = $('#stdBillsGuidanceSearch>input').val();
  1058. if (!keyword || keyword === '') {
  1059. $('#billsGuidanceSearchResult').hide();
  1060. return;
  1061. }
  1062. let result = bills.tree.items.filter(function (item) {
  1063. let codeIs = item.data.code ? item.data.code.indexOf(keyword) !== -1 : false;
  1064. let nameIs = item.data.name ? item.data.name.indexOf(keyword) !== -1 : false;
  1065. return codeIs || nameIs;
  1066. });
  1067. result.sort(function (x, y) {
  1068. return x.serialNo() - y.serialNo();
  1069. });
  1070. if (result.length !== 0) {
  1071. //展开搜索出来的节点
  1072. expandSearchNodes(result);
  1073. //设置记住展开
  1074. sessionStorage.setItem('stdBillsGuidanceExpState', bills.tree.getExpState(bills.tree.items));
  1075. let sel = billsSheet.getSelections();
  1076. renderSheetFunc(billsSheet, function () {
  1077. bills.controller.setTreeSelected(result[0]);
  1078. billsSheet.setSelection(result[0].serialNo(), sel[0].col, 1, 1);
  1079. for (let node of result) {
  1080. billsSheet.getRange(node.serialNo(), -1, 1, -1).backColor('lemonChiffon');
  1081. }
  1082. });
  1083. //搜索初始定位
  1084. billsSheet.showRow(result[0].serialNo(), GC.Spread.Sheets.VerticalPosition.center);
  1085. //查找下一条
  1086. $('#nextBillsGuidance').show();
  1087. $('#nextBillsGuidance').unbind('click');
  1088. $('#nextBillsGuidance').bind('click', function () {
  1089. let cur = bills.tree.selected, resultIndex = result.indexOf(cur), sel = billsSheet.getSelections();
  1090. if (resultIndex === result.length - 1) {
  1091. bills.controller.setTreeSelected(result[0]);
  1092. billsSheet.setSelection(result[0].serialNo(), sel[0].col, 1, 1);
  1093. billsSheet.showRow(result[0].serialNo(), GC.Spread.Sheets.VerticalPosition.center);
  1094. } else {
  1095. bills.controller.setTreeSelected(result[resultIndex + 1]);
  1096. billsSheet.setSelection(result[resultIndex + 1].serialNo(), sel[0].col, 1, 1);
  1097. billsSheet.showRow(result[resultIndex + 1].serialNo(), GC.Spread.Sheets.VerticalPosition.center);
  1098. }
  1099. });
  1100. //查找上一条
  1101. $('#preBillsGuidance').show();
  1102. $('#preBillsGuidance').unbind('click');
  1103. $('#preBillsGuidance').bind('click', function () {
  1104. let cur = bills.tree.selected, resultIndex = result.indexOf(cur), sel = billsSheet.getSelections();
  1105. if (resultIndex === 0) {
  1106. bills.controller.setTreeSelected(result[result.length - 1]);
  1107. billsSheet.setSelection(result[result.length - 1].serialNo(), sel[0].col, 1, 1);
  1108. billsSheet.showRow(result[result.length - 1].serialNo(), GC.Spread.Sheets.VerticalPosition.center);
  1109. } else {
  1110. bills.controller.setTreeSelected(result[resultIndex - 1]);
  1111. billsSheet.setSelection(result[resultIndex - 1].serialNo(), sel[0].col, 1, 1);
  1112. billsSheet.showRow(result[resultIndex - 1].serialNo(), GC.Spread.Sheets.VerticalPosition.center);
  1113. }
  1114. });
  1115. } else {
  1116. billsLibObj.clearHighLight(bills.workBook);
  1117. $('#nextBillsGuidance').hide();
  1118. $('#preBillsGuidance').hide();
  1119. }
  1120. $('#billsGuidanceSearchResultCount').text('搜索结果:' + result.length);
  1121. $('#billsGuidanceSearchResult').show();
  1122. autoFlashHeight();
  1123. refreshWorkBook();
  1124. });
  1125. //搜索框回车
  1126. $('#stdBillsGuidanceSearch>input').bind('keypress', function (event) {
  1127. if(event.keyCode === 13){
  1128. $(this).blur();
  1129. $('#stdBillsGuidanceSearch>div>button').click();
  1130. }
  1131. });
  1132. // 关闭搜索结果
  1133. $('#closeSearchBillsGuidance').click(function () {
  1134. $('#billsGuidanceSearchResult').hide();
  1135. billsLibObj.clearHighLight(bills.workBook);
  1136. autoFlashHeight();
  1137. refreshWorkBook();
  1138. });
  1139. }
  1140. //刷新表
  1141. //@return {void}
  1142. function refreshWorkBook(){
  1143. if(bills.workBook){
  1144. bills.workBook.refresh();
  1145. }
  1146. if(guideItem.workBook){
  1147. guideItem.workBook.refresh();
  1148. }
  1149. if(elfItem.workBook){
  1150. elfItem.workBook.refresh();
  1151. }
  1152. }
  1153. return {initViews, bindBtn, refreshWorkBook, setColumnWidthByRate, locateAtBills, bills, elfItem};
  1154. })();
  1155. $(document).ready(function(){
  1156. billsGuidance.bindBtn();
  1157. });