composition_spread.js 9.8 KB

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