uploadExcelByUrl.js 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265
  1. import LuckyExcel from 'luckyexcel';
  2. import { getToken } from '@/utils/utils';
  3. import moment from 'moment';
  4. window.moment = moment
  5. const uploadExcelByUrl = (nodeType, versionId, project) => {
  6. const TEMPLATE_URL =
  7. 'https://water-service-test.oss-cn-hangzhou.aliyuncs.com/public/bom/psr1008.xlsx';
  8. // 'https://gt-digitization.oss-cn-hangzhou.aliyuncs.com/public/bom/psr0913.xlsx';
  9. return new Promise((resolve, reject) => {
  10. LuckyExcel.transformExcelToLuckyByUrl(
  11. TEMPLATE_URL,
  12. '模板.xlsx',
  13. async (exportJson, luckysheetfile) => {
  14. let [record] = await getExcel(versionId);
  15. let len = exportJson.sheets.length;
  16. const excelData = exportJson.sheets;
  17. delete record.id;
  18. record.index = len + '_' + Math.floor(Math.random() * 100);
  19. record.status = '0';
  20. record.name = '清单';
  21. // var sheets = [...excelData, record];
  22. var res = [];
  23. const category = getCategoryData(record);
  24. // 处理Estimate表
  25. // initEstimate(sheets[0], category);
  26. // 处理psr预算
  27. excelData[1].status = 1;
  28. res.push(initPSR(excelData[1], category, project?.project_name));
  29. if (nodeType == 4) {
  30. // 处理现金流
  31. res.push(initActual(excelData[3], category, project));
  32. }
  33. res.push(record);
  34. // 隐藏Estimate表
  35. excelData[0].hide = 1;
  36. excelData[0].status = 0;
  37. res.push(excelData[0]);
  38. resolve(res.map((item, index) => ({ ...item, order: index })));
  39. }
  40. );
  41. });
  42. };
  43. async function getExcel(gridKey) {
  44. var formData = new FormData();
  45. formData.append('gridKey', gridKey);
  46. let res = await fetch(
  47. `/api/v1/purchase/record/sheet?gridKey=${gridKey}&JWT-TOKEN=${getToken()}`,
  48. {
  49. method: 'POST',
  50. body: formData,
  51. }
  52. ).then(response => response.text());
  53. return JSON.parse(JSON.parse(res));
  54. }
  55. function getCellValue(cell) {
  56. let v = '';
  57. if (cell.v) {
  58. v = cell.v;
  59. } else if (cell?.ct?.s) {
  60. v = cell.ct.s.map(item => item.v).join('');
  61. }
  62. return v;
  63. }
  64. function formatNumber(str) {
  65. if (str.length < 6) return str;
  66. const number = parseFloat(str);
  67. if (!isNaN(number) && number % 1 !== 0) {
  68. return number.toFixed(1);
  69. }
  70. return str;
  71. }
  72. // 根据清单获取表分类总价
  73. function getCategoryData(bom) {
  74. let bomData = [],
  75. bomTitle = {};
  76. bom.celldata.forEach(item => {
  77. let v = getCellValue(item.v);
  78. if (item.r == 0) {
  79. // 设置表头
  80. bomTitle[item.c] = v;
  81. } else {
  82. let key = bomTitle[item.c];
  83. if (!bomData[item.r - 1]) {
  84. bomData[item.r - 1] = {};
  85. }
  86. bomData[item.r - 1][key] = v;
  87. }
  88. });
  89. let category = {
  90. 'GT-UF膜': 0,
  91. 原平制造: 0,
  92. 其它膜: 0,
  93. 水泵: 0,
  94. 阀门: 0,
  95. 加药系统: 0,
  96. 过滤器: 0,
  97. 空压机: 0,
  98. 非标: 0,
  99. 仪表: 0,
  100. 电气自控: 0,
  101. 双胞胎硬件: 0,
  102. 材料: 0,
  103. 安装: 0,
  104. 土建: 0,
  105. 运输: 0,
  106. 其它: 0,
  107. };
  108. bomData.forEach(item => {
  109. if (category.hasOwnProperty(item['类别'])) {
  110. let price = parseFloat(item['总价(元)']);
  111. if (isNaN(price)) return;
  112. category[item['类别']] += price;
  113. }
  114. });
  115. return category;
  116. }
  117. // 处理现金流表
  118. function initActual(actual, category, project) {
  119. let actualCategory = [];
  120. actual.celldata.forEach((item, i, celldata) => {
  121. if (item.c == 0 && item.v?.v) {
  122. // LuckyExcel会将序号转float后再次转回string,导致小数出现精度问题
  123. // 序号后超过2位数的固定处理,不超过两位数的保留一位小数
  124. switch (item.r) {
  125. case 65:
  126. item.v.v = '5.10';
  127. break;
  128. case 66:
  129. item.v.v = '5.11';
  130. break;
  131. case 126:
  132. item.v.v = '9.12';
  133. break;
  134. case 127:
  135. item.v.v = '9.13';
  136. break;
  137. case 147:
  138. item.v.v = '10.12';
  139. break;
  140. case 148:
  141. item.v.v = '10.13';
  142. break;
  143. case 262:
  144. item.v.v = '17.15';
  145. break;
  146. case 264:
  147. item.v.v = '17.17';
  148. case 266:
  149. item.v.v = '17.19';
  150. break;
  151. default:
  152. // 处理序号转float出现多余小数的情况
  153. item.v.v = formatNumber(item.v?.v);
  154. break;
  155. }
  156. } else if (item.c == 1 && item.r == 0) {
  157. item.v.v = project?.project_name;
  158. } else if (item.c == 1 && item.r == 1) {
  159. item.v.v = project?.project_full_code;
  160. } else if (item.c == 2) {
  161. // 清单分类的总价填入对应预算列
  162. // c=2 为名称列
  163. let value = getCellValue(item.v);
  164. // 判断该行是否为类型总列
  165. if (category.hasOwnProperty(value)) {
  166. // 名称后第三列为预算列
  167. celldata[i + 3].v.v = category[value];
  168. }
  169. } else if (item.c == 12 && item.r == 5) {
  170. // 设置第一个月时间
  171. let start_date = moment("1900-01-01 00:00:00");
  172. let end_date = moment().startOf('month')
  173. item.v.v = end_date.diff(start_date, 'days');
  174. }
  175. });
  176. return actual;
  177. }
  178. // 处理毛利概算表
  179. function initEstimate(estimate, category) {
  180. estimate.celldata.forEach(item => {
  181. if (item.r == 15 && item.c == 2) {
  182. // 金科制造中心-UF膜
  183. item.v.v = category['GT-UF膜'];
  184. } else if (item.r == 14 && item.c == 2) {
  185. // 金科制造中心设备制造费
  186. item.v.v = category['原平制造'];
  187. } else if (item.r == 16 && item.c == 2) {
  188. // 设备购置费
  189. item.v.v =
  190. category['其它膜'] +
  191. category['水泵'] +
  192. category['阀门'] +
  193. category['加药系统'] +
  194. category['过滤器'] +
  195. category['空压机'] +
  196. category['非标'] +
  197. category['仪表'] +
  198. category['电气自控'] +
  199. category['材料'] +
  200. category['运输'] +
  201. category['其它'];
  202. } else if (item.r == 18 && item.c == 2) {
  203. // 数字双胞胎
  204. item.v.v = category['双胞胎硬件'];
  205. } else if (item.r == 19 && item.c == 2) {
  206. // 安装
  207. item.v.v = category['安装'];
  208. } else if (item.r == 20 && item.c == 2) {
  209. // 土建
  210. item.v.v = category['土建'];
  211. }
  212. });
  213. return estimate;
  214. }
  215. // 处理PSR表预算
  216. function initPSR(psr, category, projectName) {
  217. psr.celldata.forEach(item => {
  218. if (item.r == 0 && item.c == 1) {
  219. item.v.v = projectName;
  220. } else if (item.r == 38 && item.c == 2) {
  221. item.v.v = category['GT-UF膜'];
  222. } else if (item.r == 37 && item.c == 2) {
  223. item.v.v = category['原平制造'];
  224. } else if (item.r == 36 && item.c == 2) {
  225. item.v.v =
  226. category['其它膜'] +
  227. category['水泵'] +
  228. category['阀门'] +
  229. category['加药系统'] +
  230. category['过滤器'] +
  231. category['空压机'] +
  232. category['非标'] +
  233. category['仪表'] +
  234. category['电气自控'] +
  235. category['材料'] +
  236. category['运输'] +
  237. category['其它'];
  238. } else if (item.r == 39 && item.c == 2) {
  239. item.v.v = category['双胞胎硬件'];
  240. } else if (item.r == 40 && item.c == 2) {
  241. item.v.v = category['安装'];
  242. } else if (item.r == 41 && item.c == 2) {
  243. item.v.v = category['土建'];
  244. }
  245. });
  246. return psr;
  247. }
  248. export default uploadExcelByUrl;