project_glj_spread.js 13 KB

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