project_glj_spread.js 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458
  1. /**
  2. * 项目工料机相关spread
  3. *
  4. * @author CaiAoLin
  5. * @date 2017/7/19
  6. * @version
  7. */
  8. /**
  9. * 构造函数
  10. *
  11. * @return {void}
  12. */
  13. function ProjectGLJSpread() {
  14. this.isChanging = false;
  15. this.sheetObj = null;
  16. this.firstMachineRow = -1;
  17. this.firstMixRatioRow = -1;
  18. this.successCallback = null;
  19. this.supplyType = ['自行采购', '部分甲供', '完全甲供', '甲定乙供'];
  20. // 工料机类型是混凝土、砂浆、配合比、机械(不包括机械组成物)时,供货方式列只读。
  21. this.supplyReadonlyType = [GLJTypeConst.CONCRETE, GLJTypeConst.MORTAR, GLJTypeConst.MIX_RATIO, GLJTypeConst.GENERAL_MACHINE];
  22. }
  23. /**
  24. * 初始化
  25. *
  26. * @return {object}
  27. */
  28. ProjectGLJSpread.prototype.init = function () {
  29. // 供货方式类型
  30. let supplySelect = [];
  31. for(let index in this.supplyType) {
  32. supplySelect.push({
  33. text: this.supplyType[index],
  34. value: index
  35. });
  36. }
  37. let selectBox = new GC.Spread.Sheets.CellTypes.ComboBox();
  38. selectBox.items(supplySelect);
  39. selectBox.editorValueType(GC.Spread.Sheets.CellTypes.EditorValueType.text);
  40. let header = [
  41. {name: '编码', field: 'code', visible: true},
  42. {name: '名称', field: 'name', visible: true},
  43. {name: '规格型号', field: 'specs', visible: true},
  44. {name: '单位', field: 'unit', visible: true},
  45. {name: 'ID', field: 'id', visible: false},
  46. {name: '类型', field: 'unit_price.type', visible: false},
  47. {name: '总消耗量', field: 'quantity', visible: true},
  48. {name: '基价单价', field: "unit_price.base_price", visible: true},
  49. {name: '调整基价', field: 'adjust_price', visible: true},
  50. {name: '市场单价', field: "unit_price.market_price", visible: true, validator: 'number'},
  51. {
  52. name: '是否暂估',
  53. field: 'is_evaluate',
  54. visible: true,
  55. cellType: new GC.Spread.Sheets.CellTypes.CheckBox(),
  56. validator: 'boolean'
  57. },
  58. {name: '供货方式', field: 'supply', visible: true, cellType: selectBox},
  59. {name: '甲供数量', field: 'supply_quantity', visible: true},
  60. {name: '交货方式', field: 'delivery', visible: true},
  61. {name: '送达地点', field: 'delivery_address', visible: true},
  62. {
  63. name: '不调价',
  64. field: 'is_adjust_price',
  65. visible: true,
  66. cellType: new GC.Spread.Sheets.CellTypes.CheckBox(),
  67. validator: 'boolean'
  68. },
  69. {name: 'UID', field: 'unit_price.id', visible: false},
  70. {name: '工料机ID', field: 'glj_id', visible: false},
  71. {name: '组成物消耗量', field: 'consumption', visible: false},
  72. {name: '父级关联编码', field: 'connect_code', visible: false},
  73. {name: '消耗量', field: 'ratio_data', visible: false},
  74. ];
  75. let sourceData = jsonData;
  76. this.sheetObj = new CommonSpreadJs(header);
  77. this.sheetObj.init('project-glj');
  78. // 获取列号
  79. let isEvaluateColumn = this.sheetObj.getFieldColumn('is_evaluate');
  80. let isAdjustPriceColumn = this.sheetObj.getFieldColumn('is_adjust_price');
  81. let unitColumn = this.sheetObj.getFieldColumn('unit');
  82. let quantityColumn = this.sheetObj.getFieldColumn('quantity');
  83. let basePriceColumn = this.sheetObj.getFieldColumn('unit_price.base_price');
  84. let adjustPriceColumn = this.sheetObj.getFieldColumn('adjust_price');
  85. let marketPriceColumn = this.sheetObj.getFieldColumn('unit_price.market_price');
  86. let supplyColumn = this.sheetObj.getFieldColumn('supply');
  87. // 居中样式
  88. let centerStyleSetting = {hAlign: 1};
  89. this.sheetObj.setStyle(-1, isEvaluateColumn, centerStyleSetting);
  90. this.sheetObj.setStyle(-1, isAdjustPriceColumn, centerStyleSetting);
  91. this.sheetObj.setStyle(-1, unitColumn, centerStyleSetting);
  92. // 向右对齐样式
  93. let rightStyleSetting = {hAlign: GC.Spread.Sheets.HorizontalAlign.right};
  94. this.sheetObj.setStyle(-1, quantityColumn, rightStyleSetting);
  95. this.sheetObj.setStyle(-1, basePriceColumn, rightStyleSetting);
  96. this.sheetObj.setStyle(-1, adjustPriceColumn, rightStyleSetting);
  97. this.sheetObj.setStyle(-1, marketPriceColumn, rightStyleSetting);
  98. // 设置可编辑列
  99. this.sheetObj.setColumnEditable(marketPriceColumn);
  100. this.sheetObj.setColumnEditable(isEvaluateColumn);
  101. this.sheetObj.setColumnEditable(isAdjustPriceColumn);
  102. this.sheetObj.setColumnEditable(supplyColumn);
  103. this.sheetObj.setData(sourceData);
  104. // 取消正在加载字符提示
  105. $("#project-glj > p").hide();
  106. this.specialColumn(sourceData);
  107. // 绑定修改事件
  108. let self = this;
  109. this.sheetObj.bind(GC.Spread.Sheets.Events.ValueChanged, function(element, info) {
  110. self.updateProjectGLJField(info, self.successCallback);
  111. });
  112. // 绑定双击事件
  113. this.sheetObj.bind(GC.Spread.Sheets.Events.CellDoubleClick, function (element, info) {
  114. let column = info.col;
  115. let row = info.row;
  116. let field = self.sheetObj.getColumnField(column);
  117. let activeSheet = self.sheetObj.getSheet();
  118. // 获取类型
  119. let typeColumn = self.sheetObj.getFieldColumn('unit_price.type');
  120. let type = activeSheet.getValue(row, typeColumn);
  121. // 如果类型为混凝土、砂浆、配合比、机械,则提示
  122. if (field === 'unit_price.market_price' && canNotChangeTypeId.indexOf(type) >= 0) {
  123. alert('当前工料机的市场单价由组成物计算得出,不可直接修改');
  124. }
  125. });
  126. return this.sheetObj;
  127. };
  128. /**
  129. * 更新项目工料机中的数据字段
  130. *
  131. * @param {object} info
  132. * @param {function} callback
  133. * @return {void|boolean}
  134. */
  135. ProjectGLJSpread.prototype.updateProjectGLJField = function(info, callback) {
  136. // 获取修改的数据
  137. let column = info.col;
  138. let row = info.row;
  139. let idString = 'id';
  140. let field = projectGLJSheet.getColumnField(column);
  141. if (field === '') {
  142. return false;
  143. }
  144. let activeSheet = projectGLJSheet.getSheet();
  145. // 切割字段
  146. let fieldArray = field.split('.');
  147. idString = fieldArray.length > 1 ? 'unit_price.id' : idString;
  148. // 防止快速同时提交
  149. if (isChanging) {
  150. return false;
  151. }
  152. // 校验数据
  153. let value = info.newValue;
  154. if (!projectGLJSheet.checkData(column, value)) {
  155. alert('数据格式错误,请重新输入!');
  156. activeSheet.setValue(row, column, info.oldValue);
  157. return false;
  158. }
  159. // 获取id
  160. let idColumn = projectGLJSheet.getFieldColumn(idString);
  161. if (idColumn < 0) {
  162. return false;
  163. }
  164. let id = activeSheet.getValue(row, idColumn);
  165. // 直接在前端计算后传值后台改
  166. let extend = {};
  167. let parentMarketPrice = projectGLJSpread.compositionCalculate(row);
  168. if (parentMarketPrice !== null && Object.keys(parentMarketPrice).length > 0) {
  169. for (let activeCode in parentMarketPrice) {
  170. let tmpObject = {
  171. market_price: parentMarketPrice[activeCode],
  172. };
  173. extend[activeCode] = tmpObject;
  174. }
  175. }
  176. // 如果是供货方式则需要处理数据
  177. if (field === 'supply') {
  178. value = this.supplyType.indexOf(value);
  179. extend.supply_quantity = this.getSupplyQuantity(value, activeSheet, info);
  180. }
  181. extend = Object.keys(extend).length > 0 ? JSON.stringify(extend) : '';
  182. $.ajax({
  183. url: '/glj/update',
  184. type: 'post',
  185. data: {id: id, field: field, value: value, extend: extend},
  186. dataType: 'json',
  187. error: function() {
  188. alert('数据传输有误!');
  189. isChanging = false;
  190. },
  191. beforeSend: function() {
  192. isChanging = true;
  193. },
  194. success: function(response) {
  195. isChanging = false;
  196. // 修改失败则恢复原值
  197. if (response.err !== 0) {
  198. activeSheet.setValue(row, column, info.oldValue);
  199. alert('更改数据失败!');
  200. } else {
  201. // 成功则触发相应事件
  202. if (parentMarketPrice !== null) {
  203. info.parentMarketPrice = parentMarketPrice;
  204. }
  205. callback(field, info);
  206. }
  207. }
  208. });
  209. };
  210. /**
  211. * 设置特殊单元格数据
  212. *
  213. * @param {object} sourceData
  214. * @return {void}
  215. */
  216. ProjectGLJSpread.prototype.specialColumn = function (sourceData) {
  217. let rowCounter = 0;
  218. // 获取列号
  219. let isEvaluateColumn = this.sheetObj.getFieldColumn('is_evaluate');
  220. let marketPriceColumn = this.sheetObj.getFieldColumn('unit_price.market_price');
  221. let connectCodeColumn = this.sheetObj.getFieldColumn('connect_code');
  222. let consumptionColumn = this.sheetObj.getFieldColumn('consumption');
  223. let supplyColumn = this.sheetObj.getFieldColumn('supply');
  224. let supplyQuantity = this.sheetObj.getFieldColumn('supply_quantity');
  225. let activeSheet = this.sheetObj.getSheet();
  226. for (let data of sourceData) {
  227. // 只有材料才显示是否暂估
  228. if (materialIdList.indexOf(data.unit_price.type) < 0) {
  229. let string = new GC.Spread.Sheets.CellTypes.Text();
  230. activeSheet.setCellType(rowCounter, isEvaluateColumn, string, GC.Spread.Sheets.SheetArea.viewport);
  231. // 锁定该单元格
  232. activeSheet.getCell(rowCounter, isEvaluateColumn, GC.Spread.Sheets.SheetArea.viewport).locked(true);
  233. activeSheet.setValue(rowCounter, isEvaluateColumn, '');
  234. }
  235. // 设置供货方式列是否可选
  236. if (this.supplyReadonlyType.indexOf(data.unit_price.type) >= 0) {
  237. // 锁定该单元格
  238. activeSheet.getCell(rowCounter, supplyColumn, GC.Spread.Sheets.SheetArea.viewport).locked(true);
  239. }
  240. // 如果为部分甲供或者为全部甲供则甲供数量需要可编辑
  241. if (data.supply === 1 || data.supply === 2) {
  242. activeSheet.getCell(rowCounter, supplyQuantity, GC.Spread.Sheets.SheetArea.viewport).locked(false);
  243. }
  244. // 供货方式数据
  245. let supplyIndex = parseInt(data.supply);
  246. supplyIndex = isNaN(supplyIndex) ? 0 : supplyIndex;
  247. let supplyText = this.supplyType[supplyIndex] !== undefined ? this.supplyType[supplyIndex] : '自行采购';
  248. activeSheet.setValue(rowCounter, supplyColumn, supplyText);
  249. // 如果类型为混凝土、砂浆、配合比、机械,则市场单价和供货方式不能修改
  250. if (canNotChangeTypeId.indexOf(data.unit_price.type) >= 0) {
  251. this.firstMixRatioRow = this.firstMixRatioRow === -1 && data.unit_price.type !== GLJTypeConst.GENERAL_MACHINE ?
  252. rowCounter : this.firstMixRatioRow;
  253. this.firstMachineRow = this.firstMachineRow === -1 && data.unit_price.type === GLJTypeConst.GENERAL_MACHINE ?
  254. rowCounter : this.firstMachineRow;
  255. // 锁定该单元格
  256. activeSheet.getCell(rowCounter, marketPriceColumn, GC.Spread.Sheets.SheetArea.viewport).locked(true);
  257. activeSheet.getCell(rowCounter, supplyColumn, GC.Spread.Sheets.SheetArea.viewport).locked(true);
  258. }
  259. // 处理数据
  260. if (data.ratio_data !== undefined && data.ratio_data.length > 0) {
  261. let connectCode = [];
  262. let consumption = [];
  263. for (let tmp of data.ratio_data) {
  264. connectCode.push(tmp.connect_code);
  265. consumption.push(tmp.consumption);
  266. }
  267. let connectCodeString = connectCode.join(',');
  268. let consumptionString = consumption.join(',');
  269. activeSheet.setValue(rowCounter, connectCodeColumn, connectCodeString);
  270. activeSheet.setValue(rowCounter, consumptionColumn, consumptionString);
  271. }
  272. rowCounter++;
  273. }
  274. };
  275. /**
  276. * 计算当前行对应组成物的市场以及基价单价价格
  277. *
  278. * @param {Number} row
  279. * @return {Object}
  280. */
  281. ProjectGLJSpread.prototype.compositionCalculate = function(row) {
  282. let activeSheet = this.sheetObj.getSheet();
  283. // 获取相关列号
  284. let connectCodeColumn = this.sheetObj.getFieldColumn('connect_code');
  285. let consumptionColumn = this.sheetObj.getFieldColumn('consumption');
  286. let marketPriceColumn = this.sheetObj.getFieldColumn('unit_price.market_price');
  287. let activeConnectCode = activeSheet.getValue(row, connectCodeColumn);
  288. // 不属于组成物则忽略
  289. if (activeConnectCode === '' || activeConnectCode === null) {
  290. return null;
  291. }
  292. activeConnectCode = activeConnectCode.split(',');
  293. // 计算同级组成物的价格
  294. // 遍历所有记录
  295. let maxRow = activeSheet.getRowCount();
  296. let parentMarketPrice = {};
  297. for (let i = 0; i < maxRow; i++) {
  298. let connectCode = activeSheet.getValue(i, connectCodeColumn);
  299. if (connectCode === null) {
  300. continue;
  301. }
  302. connectCode = connectCode.split(',');
  303. // 消耗量
  304. let consumption = activeSheet.getValue(i, consumptionColumn);
  305. consumption = consumption.split(',');
  306. // 获取市场价
  307. let marketPrice = activeSheet.getValue(i, marketPriceColumn);
  308. for (let active of activeConnectCode) {
  309. let index = connectCode.indexOf(active);
  310. if (index < 0) {
  311. continue;
  312. }
  313. let rowConsumption = consumption[index] === undefined ? 0 : consumption[index];
  314. // 计算价格
  315. let rowMarketPrice = (marketPrice * rowConsumption).toDecimal(2);
  316. parentMarketPrice[active] = parentMarketPrice[active] === undefined ?
  317. rowMarketPrice : (parentMarketPrice[active] + rowMarketPrice).toDecimal(2);
  318. }
  319. }
  320. return parentMarketPrice;
  321. };
  322. /**
  323. * 组成物父类数据更新
  324. *
  325. * @param {Object} parentMarketPrice
  326. * @return {void}
  327. */
  328. ProjectGLJSpread.prototype.compositionParentUpdate = function(parentMarketPrice) {
  329. let marketPriceColumn = this.sheetObj.getFieldColumn('unit_price.market_price');
  330. let activeSheet = this.sheetObj.getSheet();
  331. // 定位到父节点,然后更新
  332. for (let code in parentMarketPrice) {
  333. let changeRow = this.sheetObj.searchKeyword(code);
  334. activeSheet.setValue(changeRow, marketPriceColumn, parentMarketPrice[code]);
  335. }
  336. };
  337. /**
  338. * 价格计算
  339. *
  340. * @param {Object} info
  341. * @return {void}
  342. */
  343. ProjectGLJSpread.prototype.priceCalculate = function(info) {
  344. let row = info.row;
  345. let typeColumn = this.sheetObj.getFieldColumn('unit_price.type');
  346. let basePriceColumn = this.sheetObj.getFieldColumn('unit_price.base_price');
  347. let adjustPriceColumn = projectGLJSheet.getFieldColumn('adjust_price');
  348. let activeSheet = this.sheetObj.getSheet();
  349. // 获取类型
  350. let type = activeSheet.getValue(row, typeColumn);
  351. // 基价单价计算
  352. switch (type) {
  353. // 主材、设备自动赋值基价单价=市场单价
  354. case GLJTypeConst.MAIN_MATERIAL:
  355. case GLJTypeConst.EQUIPMENT:
  356. activeSheet.setValue(info.row, basePriceColumn, info.newValue);
  357. break;
  358. }
  359. // 调整基价计算
  360. switch (type) {
  361. // 材料、主材、设备 调整基价=基价单价
  362. case GLJTypeConst.MAIN_MATERIAL:
  363. case GLJTypeConst.EQUIPMENT:
  364. let basePrice = activeSheet.getValue(info.row, basePriceColumn);
  365. activeSheet.setValue(info.row, adjustPriceColumn, basePrice);
  366. break;
  367. }
  368. // 市场单价计算
  369. switch (type) {
  370. // 人工、材料(普通材料)触发 需计算混凝土、砂浆、配合比、机械的市场单价
  371. case GLJTypeConst.LABOUR:
  372. case GLJTypeConst.GENERAL_MATERIAL:
  373. // 计算
  374. this.compositionParentUpdate(info.parentMarketPrice);
  375. break;
  376. }
  377. };
  378. /**
  379. * 更改供货方式
  380. *
  381. * @param {Object} info
  382. * @return {void}
  383. */
  384. ProjectGLJSpread.prototype.changeSupplyType = function(info) {
  385. let supply = info.newValue;
  386. let supplyNumber = this.supplyType.indexOf(supply) > -1 ? this.supplyType.indexOf(supply) : 0;
  387. let supplyQuantityColumn = this.sheetObj.getFieldColumn('supply_quantity');
  388. let activeSheet = this.sheetObj.getSheet();
  389. // 部分甲供时可更改甲供数量数据,其余则只读
  390. let locked = supplyNumber === 1 ? false : true;
  391. activeSheet.getCell(info.row, supplyQuantityColumn, GC.Spread.Sheets.SheetArea.viewport).locked(locked);
  392. let supplyQuantity = this.getSupplyQuantity(supplyNumber, activeSheet, info);
  393. activeSheet.setValue(info.row, supplyQuantityColumn, supplyQuantity);
  394. };
  395. /**
  396. * 根据供货方式获取甲供数量
  397. *
  398. * @param {Number} supplyType
  399. * @param {Object} activeSheet
  400. * @param {Object} info
  401. * @return {Number}
  402. */
  403. ProjectGLJSpread.prototype.getSupplyQuantity = function(supplyType, activeSheet, info) {
  404. let quantityColumn = this.sheetObj.getFieldColumn('quantity');
  405. // 获取总消耗量
  406. let quantity = activeSheet.getValue(info.row, quantityColumn);
  407. // 自行采购和甲定乙供则把甲供数量设置为0,其余情况则设置为当前总消耗量
  408. let supplyQuantity = supplyType === 0 || supplyType === 3 ? 0 : quantity;
  409. return supplyQuantity;
  410. };