composition_spread.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334
  1. /**
  2. * 组成物Spread
  3. *
  4. * @author CaiAoLin
  5. * @date 2017/7/18
  6. * @version
  7. */
  8. /**
  9. * 构造函数
  10. *
  11. * @return {void}
  12. */
  13. function CompositionSpread () {
  14. this.isChanging = false;
  15. this.sheetObj = null;
  16. this.successCallback = null;
  17. this.rightClickTarget = null;
  18. }
  19. /**
  20. * 初始化
  21. *
  22. * @param {String} target
  23. * @return {Object}
  24. */
  25. CompositionSpread.prototype.init = function(target) {
  26. let name = target === 'machine' ? '用量' : '消耗量';
  27. let header = [
  28. {name: '编码', field: 'code', visible: true},
  29. {name: '名称', field: 'name', visible: true},
  30. {name: '单位', field: 'unit', visible: true},
  31. {name: 'ID', field: 'id', visible: false},
  32. {name: '类型', field: 'unit_price.type', visible: false},
  33. {name: '定额价', field: "base_price", visible: true,decimalField:"glj.unitPrice"},
  34. {name: '调整价', field: 'adjust_price', visible: true,decimalField:"glj.unitPrice"},
  35. {name: '市场价', field: "unit_price.market_price", visible: true,decimalField:"glj.unitPrice"},
  36. {name: name, field: 'consumption', visible: true, validator: 'number',decimalField:'glj.quantity'},
  37. {name: 'CID', field: 'mix_ratio_id', visible: false},
  38. ];
  39. this.sheetObj = new CommonSpreadJs(header);
  40. this.sheetObj.init(target);
  41. // 获取列号
  42. let codeColumn = this.sheetObj.getFieldColumn('code');
  43. let unitColumn = this.sheetObj.getFieldColumn('unit');
  44. let consumptionColumn = this.sheetObj.getFieldColumn('consumption');
  45. let basePriceCol = this.sheetObj.getFieldColumn('base_price');
  46. let adjustPriceCol = this.sheetObj.getFieldColumn('adjust_price');
  47. let marketPriceCol = this.sheetObj.getFieldColumn('unit_price.market_price');
  48. // 居中样式
  49. let centerStyleSetting = {hAlign: 1};
  50. this.sheetObj.setStyle(-1, codeColumn, centerStyleSetting);
  51. this.sheetObj.setStyle(-1, unitColumn, centerStyleSetting);
  52. //靠右设置
  53. let rightStyleSetting={hAlign: 2};
  54. this.sheetObj.setStyle(-1, basePriceCol, rightStyleSetting);
  55. this.sheetObj.setStyle(-1, adjustPriceCol, rightStyleSetting);
  56. this.sheetObj.setStyle(-1, marketPriceCol, rightStyleSetting);
  57. this.sheetObj.setStyle(-1, consumptionColumn, rightStyleSetting);
  58. // 设置可编辑列
  59. this.sheetObj.setColumnEditable(consumptionColumn);
  60. // 绑定事件
  61. let self = this;
  62. this.sheetObj.bind(GC.Spread.Sheets.Events.ValueChanged, function(element, info) {
  63. self.updateConsumption(info, self.successCallback);
  64. });
  65. return this.sheetObj;
  66. };
  67. /**
  68. * 初始化右键
  69. *
  70. * @param {String} target
  71. * @return {void}
  72. */
  73. CompositionSpread.prototype.initRightClick = function(target) {
  74. let activeSheet = this.sheetObj.getSheet();
  75. let self = this;
  76. $.contextMenu({
  77. selector: '#' + target,
  78. build: function ($trigger, e) {
  79. self.rightClickTarget = SheetDataHelper.safeRightClickSelection($trigger, e, self.sheetObj.spread);
  80. return self.rightClickTarget.hitTestType === GC.Spread.Sheets.SheetArea.viewport ||
  81. self.rightClickTarget.hitTestType === GC.Spread.Sheets.SheetArea.rowHeader;
  82. },
  83. items: {
  84. "deleteMixRatio": {
  85. name: "删除",
  86. icon: 'fa-trash-o',
  87. disabled: function () {
  88. return self.rightClickTarget.row === undefined;
  89. },
  90. callback: function (key, opt) {
  91. let row = self.rightClickTarget.row;
  92. let idColumn = self.sheetObj.getFieldColumn('mix_ratio_id');
  93. let deleteId = activeSheet.getValue(row, idColumn);
  94. self.deleteComposition(deleteId, row, self.successCallback);
  95. }
  96. },
  97. }
  98. });
  99. };
  100. /**
  101. * 获取组成物数据
  102. *
  103. * @param {Number} projectGLJid
  104. * @return {void | boolean}
  105. */
  106. CompositionSpread.prototype.getRatioData = function(projectGLJid) {
  107. projectGLJid = parseInt(projectGLJid);
  108. let self = this;
  109. if (isNaN(projectGLJid) || projectGLJid <= 0) {
  110. this.sheetObj.setData(null);
  111. return false;
  112. }
  113. $.ajax({
  114. url: '/glj/get-ratio',
  115. type: 'post',
  116. data: {id: projectGLJid, project_id: scUrlUtil.GetQueryString('project')},
  117. error: function(jqXHR, textStatus, errorThrown) {
  118. ajaxErrorInfo(jqXHR, textStatus, errorThrown);
  119. self.sheetObj.setData(null);
  120. },
  121. beforeSend: function() {
  122. },
  123. success: function(response) {
  124. if (response.err === 0) {
  125. response.data = JSON.parse(response.data);
  126. // 设置数据
  127. self.sheetObj.setData(response.data);
  128. self.specialColumn(response.data);
  129. } else {
  130. self.sheetObj.setData(null);
  131. console.log('不存在对应数据');
  132. }
  133. }
  134. });
  135. };
  136. /**
  137. * 设置特殊单元格数据
  138. *
  139. * @param {object} sourceData
  140. * @return {void}
  141. */
  142. CompositionSpread.prototype.specialColumn = function(sourceData) {
  143. let rowCounter = 0;
  144. // 获取市场单价列号
  145. let consumptionColumn = this.sheetObj.getFieldColumn('consumption');
  146. let basePriceColumn = this.sheetObj.getFieldColumn('base_price');
  147. let adjustPriceColumn = this.sheetObj.getFieldColumn('adjust_price');
  148. let idColumn = this.sheetObj.getFieldColumn('mix_ratio_id');
  149. let activeSheet = this.sheetObj.getSheet();
  150. for(let data of sourceData) {
  151. // 把消耗量从对象中抽离出来
  152. if (data.ratio_data.consumption !== undefined) {
  153. activeSheet.setValue(rowCounter, consumptionColumn, data.ratio_data.consumption);
  154. activeSheet.setValue(rowCounter, idColumn, data.ratio_data.id);
  155. }
  156. data=this.sheetObj.setProjectGLJDiffPrice(data);
  157. activeSheet.setValue(rowCounter, basePriceColumn, data.base_price);
  158. activeSheet.setValue(rowCounter, adjustPriceColumn, data.adjust_price);
  159. rowCounter++;
  160. }
  161. };
  162. /**
  163. * 更新组成物消耗量或用量
  164. *
  165. * @param {Object} info
  166. * @param {function} callback
  167. * return {void}
  168. */
  169. CompositionSpread.prototype.updateConsumption = function(info, callback) {
  170. // 获取修改的数据
  171. let column = info.col;
  172. let row = info.row;
  173. let field = this.sheetObj.getColumnField(column);
  174. if (field === '') {
  175. return false;
  176. }
  177. // 防止快速同时提交
  178. if (this.isChanging) {
  179. return false;
  180. }
  181. let activeSheet = this.sheetObj.getSheet();
  182. // 校验数据
  183. let value = info.newValue;
  184. if (!this.sheetObj.checkData(column, value)) {
  185. alert('数据格式错误,请重新输入!');
  186. activeSheet.setValue(row, column, info.oldValue);
  187. return false;
  188. }
  189. // 获取id
  190. let idColumn = this.sheetObj.getFieldColumn('mix_ratio_id');
  191. if (idColumn < 0) {
  192. return false;
  193. }
  194. let id = activeSheet.getValue(row, idColumn);
  195. let [parentMarketPrice, parentBasePrice] = this.getCompositionSumPrice('modify', row, info.newValue);
  196. let self = this;
  197. $.ajax({
  198. url: '/glj/update',
  199. type: 'post',
  200. data: {id: id, field: 'mix_ratio.' + field, value: value, market_price: parentMarketPrice, base_price: parentBasePrice},
  201. dataType: 'json',
  202. error: function(jqXHR, textStatus, errorThrown) {
  203. ajaxErrorInfo(jqXHR, textStatus, errorThrown);
  204. self.isChanging = false;
  205. activeSheet.setValue(row, column, info.oldValue);
  206. },
  207. beforeSend: function() {
  208. self.isChanging = true;
  209. },
  210. success: function(response) {
  211. self.isChanging = false;
  212. // 修改失败则恢复原值
  213. if (response.err !== 0) {
  214. activeSheet.setValue(row, column, info.oldValue);
  215. alert('更改数据失败!');
  216. } else {
  217. info.id = id;
  218. info.field = field;
  219. info.parentMarketPrice = parentMarketPrice;
  220. info.parentBasePrice = parentBasePrice;
  221. info.change = info.newValue - info.oldValue;
  222. callback(info);
  223. }
  224. }
  225. });
  226. };
  227. /**
  228. * 获取当前所有组成物累积的市场单价和基价单价
  229. * 用于同步修改父级市场单价和基价单价
  230. *
  231. * @param {String} scene
  232. * @param {Number} affectRow
  233. * @param {Number} newValue
  234. * @return {Array}
  235. */
  236. CompositionSpread.prototype.getCompositionSumPrice = function(scene, affectRow, newValue = 0) {
  237. let activeSheet = this.sheetObj.getSheet();
  238. // 计算父级3个价格
  239. let maxRow = activeSheet.getRowCount();
  240. // 获取对应列的列号
  241. let marketPriceColumn = this.sheetObj.getFieldColumn('unit_price.market_price');
  242. let consumptionColumn = this.sheetObj.getFieldColumn('consumption');
  243. let basePriceColumn = this.sheetObj.getFieldColumn('base_price');
  244. let parentMarketPrice = 0;
  245. let parentBasePrice = 0;
  246. for(let i = 0; i < maxRow; i++) {
  247. // 获取市场单价
  248. let marketPrice = activeSheet.getValue(i, marketPriceColumn);
  249. // 获取基价单价
  250. let basePrice = activeSheet.getValue(i, basePriceColumn);
  251. // 如果是删除则忽略即将被删除的行数据
  252. if (scene === 'delete' && affectRow === i) {
  253. continue;
  254. }
  255. // 获取消耗量(如果是当前修改的行则替换数据)
  256. let consumption = i === affectRow ? newValue : activeSheet.getValue(i, consumptionColumn);
  257. parentMarketPrice += operationWithRound(consumption,marketPrice,"glj.unitPrice","*");
  258. parentBasePrice += operationWithRound(consumption,basePrice,"glj.unitPrice","*");
  259. }
  260. parentMarketPrice = parentMarketPrice.toDecimal(getDecimal("glj.unitPrice"));
  261. parentBasePrice = parentBasePrice.toDecimal(getDecimal("glj.unitPrice"));
  262. return [parentMarketPrice, parentBasePrice]
  263. };
  264. /**
  265. * 删除组成物
  266. *
  267. * @param {Number} id
  268. * @param {Number} row
  269. * @param {function} callback
  270. * @return {void | boolean}
  271. */
  272. CompositionSpread.prototype.deleteComposition = function (id, row, callback) {
  273. id = parseInt(id);
  274. if (isNaN(id) || id <= 0) {
  275. alert('参数错误!');
  276. }
  277. if (isDeleting) {
  278. return false;
  279. }
  280. let activeSheet = this.sheetObj.getSheet();
  281. // 获取当前行的消耗量
  282. let consumptionColumn = this.sheetObj.getFieldColumn('consumption');
  283. let consumption = activeSheet.getValue(row, consumptionColumn);
  284. let self = this;
  285. $.ajax({
  286. url: '/glj/delete-ratio',
  287. type: 'post',
  288. data: {id: id},
  289. dataType: 'json',
  290. error: function(jqXHR, textStatus, errorThrown) {
  291. ajaxErrorInfo(jqXHR, textStatus, errorThrown);
  292. isDeleting = false;
  293. alert('服务器繁忙');
  294. },
  295. beforeSend: function() {
  296. isDeleting = true;
  297. },
  298. success: function(response) {
  299. if (response.err === 0) {
  300. // 计算同级的市场单价和基价单价
  301. let [parentMarketPrice, parentBasePrice] = self.getCompositionSumPrice('delete', row);
  302. let info = {
  303. parentMarketPrice: parentMarketPrice,
  304. parentBasePrice: parentBasePrice,
  305. change: -consumption
  306. };
  307. activeSheet.setValue(row, consumptionColumn, 0);
  308. callback(info);
  309. }
  310. }
  311. });
  312. };