wap_controller.js 53 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182
  1. 'use strict';
  2. /**
  3. * 登录页面控制器
  4. *
  5. * @author CaiAoLin
  6. * @date 2017/11/15
  7. * @version
  8. */
  9. const URL = require('url');
  10. const maintainConst = require('../const/maintain');
  11. const auditConst = require('../const/audit');
  12. const tenderConst = require('../const/tender');
  13. const changeConst = require('../const/change');
  14. const advanceConst = require('../const/advance');
  15. const materialConst = require('../const/material');
  16. const fs = require('fs');
  17. const path = require('path');
  18. const sendToWormhole = require('stream-wormhole');
  19. const moment = require('moment');
  20. const auditType = require('../const/audit').auditType;
  21. module.exports = app => {
  22. class WapController extends app.BaseController {
  23. /**
  24. * 登录页面
  25. *
  26. * @param {Object} ctx - egg全局页面
  27. * @return {void}
  28. */
  29. async index(ctx) {
  30. if (!ctx.helper.isMobile(ctx.request.header['user-agent'])) {
  31. ctx.redirect('/');
  32. return;
  33. }
  34. const errorMessage = ctx.session.loginError;
  35. // 显示完删除
  36. ctx.session.loginError = null;
  37. // 获取系统维护信息
  38. const maintainData = await ctx.service.maintain.getDataById(1);
  39. if (!ctx.app.config.is_debug) {
  40. await ctx.service.maintain.syncMaintainData();
  41. }
  42. let projectData = '';
  43. if (ctx.session.wapTenderID) {
  44. const tenderData = await ctx.service.tender.getDataById(ctx.session.wapTenderID);
  45. if (tenderData) projectData = await ctx.service.project.getDataById(tenderData.project_id);
  46. }
  47. const renderData = {
  48. maintainData,
  49. maintainConst,
  50. errorMessage,
  51. projectData,
  52. };
  53. await ctx.render('wap/login.ejs', renderData);
  54. }
  55. /**
  56. * 登录操作
  57. *
  58. * @param {Object} ctx - egg全局变量
  59. * @return {void}
  60. */
  61. async login(ctx) {
  62. let loginType = ctx.request.body.type;
  63. try {
  64. loginType = parseInt(loginType);
  65. const result = await ctx.service.projectAccount.accountLogin(ctx.request.body, loginType);
  66. if (!result) {
  67. throw '用户名或密码错误';
  68. }
  69. if (result === 2) {
  70. // 判断是否有设置停用提示,有则展示
  71. const msg = await ctx.service.projectStopmsg.getMsg(ctx.session.sessionProject.id);
  72. throw msg;
  73. }
  74. // 调用 rotateCsrfSecret 刷新用户的 CSRF token
  75. ctx.rotateCsrfSecret();
  76. // 判断是否已经有对应用户信息,没有则跳转初始化页面
  77. const needBoot = await ctx.service.customer.isNeedBoot(ctx.request.body);
  78. const url = needBoot ? '/boot' : '/wap/dashboard';
  79. const query = URL.parse(ctx.request.header.referer, true).query;
  80. let referer = '';
  81. if (ctx.session.wapTenderID) {
  82. referer = query.referer ? query.referer + '#shenpi' : url;
  83. ctx.session.wapTenderID = null;
  84. }
  85. ctx.redirect(referer ? referer : url);
  86. } catch (error) {
  87. this.log(error);
  88. ctx.session.loginError = error;
  89. ctx.redirect('/wap');
  90. }
  91. }
  92. /**
  93. * 退出登录
  94. *
  95. * @param {Object} ctx - egg全局变量
  96. * @return {void}
  97. */
  98. async logout(ctx) {
  99. // 删除session并跳转
  100. ctx.session = null;
  101. ctx.redirect('/wap');
  102. }
  103. /**
  104. * 待办页
  105. *
  106. * @param {Object} ctx - egg全局变量
  107. * @return {void}
  108. */
  109. async dashboard(ctx) {
  110. // 获取待审批的期
  111. const auditStages = await ctx.service.stageAudit.getAuditStageByWap(ctx.session.sessionUser.accountId);
  112. const subProjects = [];
  113. for (const audit of auditStages) {
  114. if (audit.status !== auditConst.stage.status.uncheck) {
  115. const isLastage = await ctx.service.stage.isLastStage(audit.tid, audit.id);
  116. if (isLastage) await this.ctx.service.stage.checkStageGatherData(audit);
  117. }
  118. audit.gather_tp = ctx.helper.sum([audit.contract_tp, audit.qc_tp, audit.pc_tp]);
  119. audit.end_contract_tp = ctx.helper.sum([audit.contract_tp, audit.pre_contract_tp, audit.contract_pc_tp]);
  120. audit.end_qc_tp = ctx.helper.sum([audit.qc_tp, audit.pre_qc_tp, audit.qc_pc_tp]);
  121. audit.pre_gather_tp = ctx.helper.add(audit.pre_contract_tp, audit.pre_qc_tp);
  122. audit.end_gather_tp = ctx.helper.add(audit.gather_tp, audit.pre_gather_tp);
  123. let sp = null;
  124. if (audit.spid) {
  125. if (ctx.helper._.findIndex(subProjects, { id: audit.spid }) !== -1) {
  126. sp = ctx.helper._.find(subProjects, { id: audit.spid });
  127. } else {
  128. sp = await ctx.service.subProject.getDataById(audit.spid);
  129. subProjects.push(sp);
  130. }
  131. }
  132. if (sp) {
  133. const pageShow = JSON.parse(sp.page_show);
  134. audit.closeWapYfSf = pageShow.closeWapYfSf || 0;
  135. } else {
  136. audit.closeWapYfSf = 0;
  137. }
  138. }
  139. // 获取待审批的变更期
  140. const auditChanges = await ctx.service.changeAudit.getAuditChangeByWap(ctx.session.sessionUser.accountId);
  141. // 获取待审批的变更立项
  142. const auditChangeProjects = [];
  143. const changeProjects = await ctx.service.changeProjectAudit.getAuditChangeProjectByWap(ctx.session.sessionUser.accountId);
  144. for (const cp of changeProjects) {
  145. let sp = null;
  146. if (cp.spid) {
  147. if (ctx.helper._.findIndex(subProjects, { id: cp.spid }) !== -1) {
  148. sp = ctx.helper._.find(subProjects, { id: cp.spid });
  149. } else {
  150. sp = await ctx.service.subProject.getDataById(cp.spid);
  151. subProjects.push(sp);
  152. }
  153. }
  154. if (sp) {
  155. const pageShow = JSON.parse(sp.page_show);
  156. if (pageShow.openChangeProject) {
  157. auditChangeProjects.push(cp);
  158. }
  159. }
  160. }
  161. // 获取待审批的变更申请
  162. const auditChangeApplys = [];
  163. const changeApplys = await ctx.service.changeApplyAudit.getAuditChangeApplyByWap(ctx.session.sessionUser.accountId);
  164. for (const ca of changeApplys) {
  165. let sp = null;
  166. if (ca.spid) {
  167. if (ctx.helper._.findIndex(subProjects, { id: ca.spid }) !== -1) {
  168. sp = ctx.helper._.find(subProjects, { id: ca.spid });
  169. } else {
  170. sp = await ctx.service.subProject.getDataById(ca.spid);
  171. subProjects.push(sp);
  172. }
  173. }
  174. if (sp) {
  175. const pageShow = JSON.parse(sp.page_show);
  176. if (pageShow.openChangeApply) {
  177. auditChangeApplys.push(ca);
  178. }
  179. }
  180. }
  181. // 获取待审批的变更方案
  182. const auditChangePlans = [];
  183. const changePlans = await ctx.service.changePlanAudit.getAuditChangePlanByWap(ctx.session.sessionUser.accountId);
  184. for (const cp of changePlans) {
  185. let sp = null;
  186. if (cp.spid) {
  187. if (ctx.helper._.findIndex(subProjects, { id: cp.spid }) !== -1) {
  188. sp = ctx.helper._.find(subProjects, { id: cp.spid });
  189. } else {
  190. sp = await ctx.service.subProject.getDataById(cp.spid);
  191. subProjects.push(sp);
  192. }
  193. }
  194. if (sp) {
  195. const pageShow = JSON.parse(sp.page_show);
  196. if (pageShow.openChangePlan) {
  197. auditChangePlans.push(cp);
  198. }
  199. } else {
  200. auditChangePlans.push(cp);
  201. }
  202. }
  203. // 获取待审批的台账修订
  204. const auditRevise = await ctx.service.reviseAudit.getAuditReviseByWap(ctx.session.sessionUser.accountId);
  205. for (const revise of auditRevise) {
  206. const yb_audit = await ctx.service.projectAccount.getAccountInfoById(revise.audit_id);
  207. revise.yb_name = yb_audit.name;
  208. }
  209. // 获取待审批的预付款
  210. const auditAdvance = await ctx.service.advanceAudit.getAuditAdvanceByWap(ctx.session.sessionUser.accountId);
  211. const materialList = await ctx.service.materialAudit.getAuditMaterialByWap(ctx.session.sessionUser.accountId);
  212. const auditMaterials = [];
  213. for (const audit of materialList) {
  214. audit.decimal = audit.decimal ? JSON.parse(audit.decimal) : materialConst.decimal;
  215. let sp = null;
  216. if (audit.spid) {
  217. if (ctx.helper._.findIndex(subProjects, { id: audit.spid }) !== -1) {
  218. sp = ctx.helper._.find(subProjects, { id: audit.spid });
  219. } else {
  220. sp = await ctx.service.subProject.getDataById(audit.spid);
  221. subProjects.push(sp);
  222. }
  223. }
  224. if (sp) {
  225. const pageShow = JSON.parse(sp.page_show);
  226. if (pageShow.openMaterial) {
  227. auditMaterials.push(audit);
  228. }
  229. }
  230. }
  231. const renderData = {
  232. auditStages,
  233. auditChanges,
  234. auditChangeProjects,
  235. auditChangeApplys,
  236. auditChangePlans,
  237. auditMaterials,
  238. auditRevise,
  239. auditAdvance,
  240. changeConst,
  241. advanceConst,
  242. tpUnit: 2,
  243. };
  244. await ctx.render('wap/dashboard.ejs', renderData);
  245. }
  246. async subproj(ctx) {
  247. try {
  248. const renderData = {
  249. jsFiles: this.app.jsFiles.common.concat(this.app.jsFiles.subProject.wap),
  250. };
  251. renderData.projectList = await ctx.service.subProject.getSubProject(ctx.session.sessionProject.id, ctx.session.sessionUser.accountId, ctx.session.sessionUser.is_admin);
  252. renderData.tenderList = await ctx.service.tender.getManageTenderList(ctx.session.sessionProject.id);
  253. await ctx.render('wap/sub_proj.ejs', renderData);
  254. } catch (err) {
  255. ctx.log(err);
  256. ctx.session.postError = err.toString();
  257. ctx.redirect('/wap/dashboard');
  258. }
  259. }
  260. /**
  261. * 标段列表页
  262. *
  263. * @param {Object} ctx - egg全局变量
  264. * @return {void}
  265. */
  266. async list(ctx) {
  267. try {
  268. // 获取用户新建标段权利
  269. const accountInfo = await this.ctx.service.projectAccount.getDataById(ctx.session.sessionUser.accountId);
  270. const userPermission = accountInfo !== undefined && accountInfo.permission !== '' ? JSON.parse(accountInfo.permission) : null;
  271. const tenderList = await this.ctx.service.tender.getBuildList('', userPermission);
  272. for (const t of tenderList) {
  273. await this.ctx.service.tenderCache.loadTenderCache(t, this.ctx.session.sessionUser.accountId);
  274. }
  275. const categoryData = await this.ctx.service.category.getAllCategory(ctx.subProject);
  276. const valuations = await this.ctx.service.valuation.getProjectValidValuation(this.ctx.session.sessionProject.id);
  277. const renderData = {
  278. tenderList,
  279. categoryData,
  280. auditConst,
  281. userPermission,
  282. valuations,
  283. uid: this.ctx.session.sessionUser.accountId,
  284. pid: this.ctx.session.sessionProject.id,
  285. };
  286. await ctx.render('wap/list.ejs', renderData);
  287. } catch (err) {
  288. this.log(err);
  289. this.ctx.redirect('/wap/dashboard');
  290. }
  291. }
  292. /**
  293. * 标段详细页
  294. *
  295. * @param {Object} ctx - egg全局变量
  296. * @return {void}
  297. */
  298. async tender(ctx) {
  299. try {
  300. const tender = ctx.tender.data;
  301. if (tender.user_id === this.ctx.session.sessionUser.accountId && (
  302. tender.ledger_status === auditConst.ledger.status.checkNo || tender.ledger_status === auditConst.ledger.status.uncheck)) {
  303. const sum = await this.ctx.service.ledger.addUp({tender_id: tender.id/*, is_leaf: true*/});
  304. tender.total_price = sum.total_price;
  305. tender.deal_tp = sum.deal_tp;
  306. }
  307. const [change_tp, change_p_tp, change_n_tp, change_valuation_tp, change_unvaluation_tp] = await ctx.service.change.getChangeTp(ctx.tender.id);
  308. tender.change_tp = change_tp;
  309. tender.change_p_tp = change_p_tp;
  310. tender.change_n_tp = change_n_tp;
  311. tender.change_valuation_tp = change_valuation_tp;
  312. tender.change_unvaluation_tp = change_unvaluation_tp;
  313. const stages = await ctx.service.stage.getValidStages(ctx.tender.id);
  314. const lastStage = stages.length > 0 ? stages[0] : null; //await ctx.service.stage.getLastestStage(ctx.tender.id);
  315. if (lastStage) {
  316. await this.ctx.service.stage.checkStageGatherData(lastStage);
  317. tender.gather_tp = ctx.helper.sum([lastStage.contract_tp, lastStage.qc_tp, lastStage.pc_tp]);
  318. tender.end_contract_tp = ctx.helper.sum([lastStage.contract_tp, lastStage.pre_contract_tp, lastStage.contract_pc_tp]);
  319. tender.end_qc_tp = ctx.helper.sum([lastStage.qc_tp, lastStage.pre_qc_tp, lastStage.qc_pc_tp]);
  320. tender.pre_gather_tp = ctx.helper.add(lastStage.pre_contract_tp, lastStage.pre_qc_tp);
  321. tender.end_gather_tp = ctx.helper.add(tender.gather_tp, tender.pre_gather_tp);
  322. tender.yf_tp = lastStage.yf_tp;
  323. tender.qc_ratio = ctx.helper.mul(ctx.helper.div(tender.end_qc_tp, ctx.tender.info.deal_param.contractPrice, 2), 100);
  324. tender.sum = ctx.helper.add(tender.total_price, tender.change_tp);
  325. tender.pre_ratio = ctx.helper.mul(ctx.helper.div(tender.pre_gather_tp, tender.sum, 2), 100);
  326. tender.cur_ratio = ctx.helper.mul(ctx.helper.div(tender.gather_tp, tender.sum, 2), 100);
  327. tender.other_tp = ctx.helper.sub(ctx.helper.sub(tender.sum, tender.pre_gather_tp), tender.gather_tp);
  328. tender.other_ratio = Math.max(0, 100 - tender.pre_ratio - tender.cur_ratio);
  329. }
  330. const monthProgress = [];
  331. for (const s of stages) {
  332. if (s.s_time) {
  333. let progress = monthProgress.find(function(x) {
  334. return x.month === s.s_time;
  335. });
  336. if (!progress) {
  337. progress = { month: s.s_time };
  338. monthProgress.push(progress);
  339. }
  340. progress.tp = ctx.helper.add(ctx.helper.add(progress.tp, s.contract_tp), s.qc_tp);
  341. }
  342. }
  343. monthProgress.sort(function(x, y) {
  344. return Date.parse(x.month) - Date.parse(y.month);
  345. });
  346. let sum = 0;
  347. for (const p of monthProgress) {
  348. p.ratio = ctx.helper.mul(ctx.helper.div(p.tp, tender.sum, 4), 100);
  349. sum = ctx.helper.add(sum, p.tp);
  350. p.end_tp = sum;
  351. p.end_ratio = ctx.helper.mul(ctx.helper.div(p.end_tp, tender.sum, 4), 100);
  352. }
  353. // 台账修订列表
  354. const revises = await ctx.service.ledgerRevise.getReviseList(ctx.tender.id);
  355. for (const lr of revises) {
  356. if (lr.valid) {
  357. lr.curAuditor = await ctx.service.reviseAudit.getAuditorByStatus(lr.id, lr.status, lr.times);
  358. }
  359. }
  360. // 预付款期数获取
  361. const advanceList = [];
  362. for (const t of advanceConst.typeCol) {
  363. const advance = await ctx.service.advance.getLastestAdvance(ctx.tender.id, t.type, true);
  364. advanceList.push(advance);
  365. }
  366. // 材料调差
  367. const materials = await ctx.service.material.getValidMaterials(ctx.tender.id);
  368. let openMaterialTax = ctx.subProject.page_show.openMaterialTax;
  369. const tenderMsg = await ctx.service.tender.getTender(ctx.tender.id, ['material_col_show']);
  370. const material_col_show = tenderMsg.material_col_show ? JSON.parse(tenderMsg.material_col_show) : ctx.helper._.cloneDeep(tenderConst.materialColShow);
  371. let allMaterialTax = true;
  372. for (const s of materials) {
  373. if (!s.final_auditor_str || s.status !== auditConst.material.status.checked) {
  374. // 根据期状态返回展示用户
  375. s.curAuditors = await ctx.service.materialAudit.getAuditorsByStatus(s.id, s.status, s.times);
  376. if (s.status === auditConst.material.status.checked && s.curAuditors.length > 0) {
  377. const final_auditor_str = (s.curAuditors[0].audit_type === auditType.key.common)
  378. ? `${s.curAuditors[0].name}${(s.curAuditors[0].role ? '-' + s.curAuditors[0].role : '')}`
  379. : ctx.helper.transFormToChinese(s.curAuditors[0].audit_order) + '审';
  380. await ctx.service.material.defaultUpdate({ id: s.id, final_auditor_str });
  381. }
  382. }
  383. if (allMaterialTax && s.material_tax === 0) {
  384. allMaterialTax = false;
  385. }
  386. if (!openMaterialTax && s.material_tax === 1) {
  387. openMaterialTax = 1;
  388. }
  389. s.decimal = s.decimal ? JSON.parse(s.decimal) : materialConst.decimal;
  390. }
  391. const renderData = {
  392. tender,
  393. stages,
  394. revises,
  395. advanceList,
  396. materials,
  397. openMaterialTax,
  398. allMaterialTax,
  399. materialColShow: material_col_show,
  400. auditConst: auditConst.stage,
  401. auditReviseConst: auditConst.revise,
  402. auditMaterialConst: auditConst.material,
  403. advanceConst,
  404. tpUnit: ctx.tender.info.decimal.tp,
  405. monthProgress,
  406. stagesEcharts: JSON.parse(JSON.stringify(stages)).reverse(),
  407. auditType: auditConst.auditType,
  408. };
  409. if (stages.length > 0) {
  410. for (const s of stages) {
  411. // s.curAuditor = null;
  412. // 根据期状态返回展示用户
  413. s.curAuditors = await ctx.service.stageAudit.getAuditorsByStatus(s.id, s.status, s.times);
  414. if (s.status === auditConst.stage.status.checkNoPre) {
  415. s.curAuditors2 = await ctx.service.stageAudit.getAuditorsByStatus(s.id, auditConst.stage.status.checking);
  416. }
  417. }
  418. renderData.stage = stages[0];
  419. const times = renderData.stage.status === auditConst.stage.status.checkNo ? renderData.stage.times - 1 : renderData.stage.times;
  420. renderData.stage.user = await ctx.service.projectAccount.getAccountInfoById(renderData.stage.user_id);
  421. renderData.stage.auditors = await ctx.service.stageAudit.getAuditors(renderData.stage.id, times);
  422. // 获取审批流程中左边列表
  423. renderData.stage.auditors2 = await ctx.service.stageAudit.getAuditGroupByList(renderData.stage.id, times);
  424. }
  425. await ctx.render('wap/tender.ejs', renderData);
  426. } catch (err) {
  427. this.log(err);
  428. ctx.redirect('/wap/sp/' + ctx.subProject.id + '/list');
  429. }
  430. }
  431. /**
  432. * 期审批详细页
  433. *
  434. * @param {Object} ctx - egg全局变量
  435. * @return {void}
  436. */
  437. async stage(ctx) {
  438. try {
  439. const tender = ctx.tender.data;
  440. // const stages = await ctx.service.stage.getValidStages(ctx.tender.id);
  441. // const lastStage = stages.length > 0 ? stages[0] : null;
  442. // if (lastStage) {
  443. // await this.ctx.service.stage.checkStageGatherData(lastStage);
  444. // }
  445. const stage = ctx.stage;
  446. if (stage) {
  447. if (stage.status !== auditConst.stage.status.checked) await this.ctx.service.stage.checkStageGatherData(stage);
  448. stage.tp = this.ctx.helper.sum([stage.contract_tp, stage.qc_tp, stage.pc_tp]);
  449. stage.pre_tp = this.ctx.helper.add(stage.pre_contract_tp, stage.pre_qc_tp);
  450. stage.end_tp = this.ctx.helper.add(stage.pre_tp, stage.tp);
  451. }
  452. await ctx.service.stage.loadStageAuditViewData(stage);
  453. const renderData = {
  454. moment,
  455. tender,
  456. stage,
  457. auditConst: auditConst.stage,
  458. auditType,
  459. };
  460. // const times = renderData.stage.status === auditConst.stage.status.checkNo ? renderData.stage.times - 1 : renderData.stage.times;
  461. // renderData.stage.user = await ctx.service.projectAccount.getAccountInfoById(renderData.stage.user_id);
  462. // renderData.stage.auditors = await ctx.service.stageAudit.getAuditors(renderData.stage.id, times);
  463. // // 获取审批流程中左边列表
  464. // renderData.stage.auditors2 = await ctx.service.stageAudit.getAuditGroupByList(renderData.stage.id, times);
  465. renderData.stage.lastAuditors = await ctx.service.stageAudit.getAuditorsByStatus(stage.id, stage.status, stage.times);
  466. await ctx.render('wap/shenpi_stage.ejs', renderData);
  467. } catch (err) {
  468. this.log(err);
  469. ctx.redirect('/wap/sp/' + ctx.subProject.id + '/list');
  470. }
  471. }
  472. /**
  473. * 调差期审批详细页
  474. *
  475. * @param {Object} ctx - egg全局变量
  476. * @return {void}
  477. */
  478. async material(ctx) {
  479. try {
  480. const tender = ctx.tender.data;
  481. const material = ctx.material;
  482. await ctx.service.material.loadMaterialAuditViewData(material);
  483. const renderData = {
  484. moment,
  485. tender,
  486. material,
  487. auditConst: auditConst.material,
  488. auditType,
  489. };
  490. renderData.material.m_tax_tp = renderData.material.m_tax_tp ? renderData.material.m_tax_tp : renderData.material.m_tp;
  491. renderData.pre_tp_hs = await ctx.service.material.getPreTpHs(ctx.tender.id, ctx.material.order, ctx.material.decimal.tp);
  492. renderData.ex_pre_tp_hs = await ctx.service.material.getExPreTpHs(ctx.tender.id, ctx.material.order, ctx.material.decimal.tp);
  493. renderData.months = ctx.material.months ? ctx.material.months.split(',') : [];
  494. renderData.material.lastAuditors = await ctx.service.materialAudit.getAuditorsByStatus(material.id, material.status, material.times);
  495. renderData.old_had_tax = await ctx.service.material.getOldMaterialTax(ctx.tender.id, ctx.material.order);
  496. await ctx.render('wap/shenpi_material.ejs', renderData);
  497. } catch (err) {
  498. this.log(err);
  499. ctx.redirect('/wap/sp/' + ctx.subProject.id + '/list');
  500. }
  501. }
  502. /**
  503. * 工程变更列表页
  504. *
  505. * @param {Object} ctx - egg全局变量
  506. * @return {void}
  507. */
  508. async changeIndex(ctx) {
  509. try {
  510. // 变更令列表
  511. const changes = await ctx.service.change.getListByStatus(ctx.tender.id, 0, 0);
  512. for (const c of changes) {
  513. c.showApprovalBtn = false;
  514. c.curAuditors = await ctx.service.changeAudit.getAuditorsByStatus(c.cid, c.status, c.times);
  515. if (c.status === auditConst.change.status.checkNoPre) {
  516. c.curAuditors2 = await ctx.service.changeAudit.getAuditorsByStatus(c.cid, auditConst.change.status.checking, c.times);
  517. const curAudit = c.curAuditors2.find(function(x) {
  518. return x.uid === ctx.session.sessionUser.accountId;
  519. });
  520. if (curAudit && curAudit.status === auditConst.change.status.checking) {
  521. c.showApprovalBtn = true;
  522. }
  523. } else {
  524. const curAudit = c.curAuditors.find(function(x) {
  525. return x.uid === ctx.session.sessionUser.accountId;
  526. });
  527. if (curAudit && curAudit.status === auditConst.change.status.checking) {
  528. c.showApprovalBtn = true;
  529. }
  530. }
  531. }
  532. // 变更立项列表
  533. let changeProjects = [];
  534. if (ctx.subProject.page_show.openChangeProject) {
  535. changeProjects = await ctx.service.changeProject.getListByStatus(ctx.tender.id, 0, 0);
  536. for (const c of changeProjects) {
  537. c.showApprovalBtn = false;
  538. c.curAuditors = await ctx.service.changeProjectAudit.getAuditorsByStatus(c.id, c.status, c.times);
  539. const curAudit = c.curAuditors.find(function(x) {
  540. return x.aid === ctx.session.sessionUser.accountId;
  541. });
  542. if (curAudit && curAudit.status === auditConst.changeProject.status.checking) {
  543. c.showApprovalBtn = true;
  544. }
  545. }
  546. }
  547. // 变更申请列表
  548. let changeApplys = [];
  549. if (ctx.subProject.page_show.openChangeApply) {
  550. changeApplys = await ctx.service.changeApply.getListByStatus(ctx.tender.id, 0, 0);
  551. for (const c of changeApplys) {
  552. c.showApprovalBtn = false;
  553. c.curAuditors = await ctx.service.changeApplyAudit.getAuditorsByStatus(c.id, c.status, c.times);
  554. const curAudit = c.curAuditors.find(function(x) {
  555. return x.aid === ctx.session.sessionUser.accountId;
  556. });
  557. if (curAudit && curAudit.status === auditConst.changeApply.status.checking) {
  558. c.showApprovalBtn = true;
  559. }
  560. }
  561. }
  562. // 变更方案列表
  563. let changePlans = [];
  564. if (ctx.subProject.page_show.openChangePlan) {
  565. changePlans = await ctx.service.changePlan.getListByStatus(ctx.tender.id, 0, 0);
  566. for (const c of changePlans) {
  567. c.showApprovalBtn = false;
  568. c.curAuditors = await ctx.service.changePlanAudit.getAuditorsByStatus(c.id, c.status, c.times);
  569. const curAudit = c.curAuditors.find(function(x) {
  570. return x.aid === ctx.session.sessionUser.accountId;
  571. });
  572. if (curAudit && curAudit.status === auditConst.changePlan.status.checking) {
  573. c.showApprovalBtn = true;
  574. }
  575. }
  576. }
  577. const renderData = {
  578. tender: ctx.tender,
  579. changes,
  580. changeProjects,
  581. changeApplys,
  582. changePlans,
  583. auditChangeConst: auditConst.change,
  584. auditChangeProjectConst: auditConst.changeProject,
  585. auditChangeApplyConst: auditConst.changeApply,
  586. auditChangePlanConst: auditConst.changePlan,
  587. changeConst,
  588. tpUnit: ctx.tender.info.decimal.tp,
  589. auditType: auditConst.auditType,
  590. };
  591. await ctx.render('wap/shenpi_change_index.ejs', renderData);
  592. } catch (err) {
  593. this.log(err);
  594. ctx.redirect('/wap/sp/' + ctx.subProject.id + '/list');
  595. }
  596. }
  597. /**
  598. * 变更审批详细页
  599. *
  600. * @param {Object} ctx - egg全局变量
  601. * @return {void}
  602. */
  603. async change(ctx) {
  604. try {
  605. const tender = ctx.tender.data;
  606. const change = ctx.change;
  607. const times = change.status !== auditConst.change.status.checkNo && change.status !== auditConst.change.status.revise ? change.times : change.times - 1;
  608. const auditList = await ctx.service.changeAudit.getListOrderByTimes(change.cid, times);
  609. const auditGroupList = await ctx.service.changeAudit.getListGroupByTimes(change.cid, times);
  610. await ctx.service.change.loadChangeAuditViewData(ctx.change);
  611. const renderData = {
  612. moment,
  613. tender,
  614. change,
  615. auditList,
  616. auditGroupList,
  617. auditConst: auditConst.change,
  618. changeConst,
  619. tpUnit: ctx.tender.info.decimal.tp,
  620. auditType,
  621. };
  622. await ctx.render('wap/shenpi_change.ejs', renderData);
  623. } catch (err) {
  624. this.log(err);
  625. ctx.redirect('/wap/sp/' + ctx.subProject.id + '/list');
  626. }
  627. }
  628. /**
  629. * 变更立项审批详细页
  630. *
  631. * @param {Object} ctx - egg全局变量
  632. * @return {void}
  633. */
  634. async changeProject(ctx) {
  635. try {
  636. const tender = ctx.tender.data;
  637. const change = ctx.change;
  638. await ctx.service.changeProject.loadChangeAuditViewData(ctx.change);
  639. const renderData = {
  640. moment,
  641. tender,
  642. change,
  643. auditConst: auditConst.changeProject,
  644. changeConst,
  645. tpUnit: ctx.tender.info.decimal.tp,
  646. auditType,
  647. };
  648. await ctx.render('wap/shenpi_change_project.ejs', renderData);
  649. } catch (err) {
  650. this.log(err);
  651. ctx.redirect('/wap/sp/' + ctx.subProject.id + '/list');
  652. }
  653. }
  654. /**
  655. * 变更申请审批详细页
  656. *
  657. * @param {Object} ctx - egg全局变量
  658. * @return {void}
  659. */
  660. async changeApply(ctx) {
  661. try {
  662. const tender = ctx.tender.data;
  663. const change = ctx.change;
  664. await ctx.service.changeApply.loadChangeAuditViewData(ctx.change);
  665. const renderData = {
  666. moment,
  667. tender,
  668. change,
  669. auditConst: auditConst.changeApply,
  670. changeConst,
  671. tpUnit: ctx.tender.info.decimal.tp,
  672. auditType,
  673. };
  674. await ctx.render('wap/shenpi_change_apply.ejs', renderData);
  675. } catch (err) {
  676. this.log(err);
  677. ctx.redirect('/wap/sp/' + ctx.subProject.id + '/list');
  678. }
  679. }
  680. /**
  681. * 变更方案审批详细页
  682. *
  683. * @param {Object} ctx - egg全局变量
  684. * @return {void}
  685. */
  686. async changePlan(ctx) {
  687. try {
  688. const tender = ctx.tender.data;
  689. const change = ctx.change;
  690. await ctx.service.changePlan.loadChangeAuditViewData(ctx.change);
  691. const renderData = {
  692. moment,
  693. tender,
  694. change,
  695. auditConst: auditConst.changeApply,
  696. changeConst,
  697. tpUnit: ctx.tender.info.decimal.tp,
  698. auditType,
  699. };
  700. await ctx.render('wap/shenpi_change_plan.ejs', renderData);
  701. } catch (err) {
  702. this.log(err);
  703. ctx.redirect('/wap/sp/' + ctx.subProject.id + '/list');
  704. }
  705. }
  706. /**
  707. * 修订审批详细页
  708. *
  709. * @param {Object} ctx - egg全局变量
  710. * @return {void}
  711. */
  712. async revise(ctx) {
  713. try {
  714. const tender = ctx.tender.data;
  715. const revise = await ctx.service.ledgerRevise.getDataByCondition({ id: ctx.params.rid });
  716. revise.user = await ctx.service.projectAccount.getAccountInfoById(revise.uid);
  717. const times = revise.status === auditConst.revise.status.checkNo ? revise.times - 1 : revise.times;
  718. revise.curAuditor = await ctx.service.reviseAudit.getAuditorByStatus(revise.id, revise.status, times);
  719. revise.auditors = await ctx.service.reviseAudit.getAuditors(revise.id, times);
  720. console.log(times, revise.auditors);
  721. const renderData = {
  722. tender,
  723. revise,
  724. auditConst: auditConst.revise,
  725. };
  726. await ctx.render('wap/shenpi_revise.ejs', renderData);
  727. } catch (err) {
  728. this.log(err);
  729. ctx.redirect('/wap/sp/' + ctx.subProject.id + '/list');
  730. }
  731. }
  732. /**
  733. * 预付款列表页
  734. *
  735. * @param {Object} ctx - egg全局变量
  736. * @return {void}
  737. */
  738. async advance(ctx) {
  739. try {
  740. const tender = ctx.tender.data;
  741. const { decimal } = ctx.tender.info;
  742. this.decimal = decimal.pay ? decimal.payTp : decimal.tp;
  743. const advancePayTotalList = [];
  744. const advanceList = [];
  745. for (const t of advanceConst.typeCol) {
  746. const advancePayTotal = ctx.tender.info.deal_param[t.key + 'Advance'];
  747. advancePayTotalList.push(advancePayTotal);
  748. const advances = await ctx.service.advance.getAdvanceList(ctx.tender.id, t.type, this.decimal, advancePayTotal);
  749. advanceList.push(advances);
  750. }
  751. const renderData = {
  752. tender,
  753. advancePayTotalList,
  754. advanceList,
  755. auditConst: auditConst.advance,
  756. advanceConst,
  757. };
  758. await ctx.render('wap/shenpi_advance.ejs', renderData);
  759. } catch (err) {
  760. this.log(err);
  761. ctx.redirect('/wap/sp/' + ctx.subProject.id + '/list');
  762. }
  763. }
  764. /**
  765. * 预付款详情页 GET
  766. * @param {Object} ctx 全局上下文
  767. */
  768. async advanceDetail(ctx) {
  769. try {
  770. const tender = ctx.tender.data;
  771. ctx.advance.advancePayTotal = ctx.tender.info.deal_param[ advanceConst.typeCol[ctx.advance.type].key + 'Advance'];
  772. const times = ctx.advance.status === auditConst.advance.status.checkNo ? ctx.advance.times - 1 : ctx.advance.times;
  773. if (ctx.advance.status === auditConst.advance.status.checkNo) {
  774. ctx.advance.curAuditor = await ctx.service.advanceAudit.getAuditorByStatus(ctx.advance.id, ctx.advance.status, times);
  775. ctx.advance.auditors = await ctx.service.advanceAudit.getAuditors(ctx.advance.id, times);
  776. }
  777. // 获取审批流程中左边列表
  778. ctx.advance.auditors2 = await ctx.service.advanceAudit.getAuditGroupByList(ctx.advance.id, times);
  779. const renderData = {
  780. tender,
  781. advance: ctx.advance,
  782. auditConst: auditConst.advance,
  783. advanceConst,
  784. };
  785. await ctx.render('wap/shenpi_advance_detail.ejs', renderData);
  786. } catch (error) {
  787. this.log(error);
  788. ctx.redirect('/wap/tender/' + ctx.tender.id + '/advance');
  789. }
  790. }
  791. /**
  792. * 变更令审批
  793. * @param {Object} ctx - egg全局变量
  794. * @return {void}
  795. */
  796. async changeApproval(ctx) {
  797. try {
  798. const cid = ctx.request.body.change_id;
  799. const changeData = await ctx.service.change.getDataByCondition({ cid });
  800. if (!changeData) {
  801. throw '变更令数据错误';
  802. }
  803. // 判断是否到你审批,如果不是则无法审批
  804. const curAuditor = await ctx.service.changeAudit.getCurAuditors(changeData.cid, changeData.times);
  805. if (!curAuditor || (curAuditor && ctx.helper._.findIndex(curAuditor, { uid: ctx.session.sessionUser.accountId }) === -1)) {
  806. throw '该变更令当前您无权操作';
  807. }
  808. const readySettle = await ctx.service.settle.getReadySettle(changeData.tid);
  809. if (readySettle && readySettle.settle_order !== ctx.tender.data.settle_order) {
  810. throw '结算数据发生变化,请刷新页面再提交';
  811. }
  812. const status = parseInt(ctx.request.body.status);
  813. const pid = this.ctx.session.sessionProject.id;
  814. let result = false;
  815. switch (status) {
  816. case 3:// 审批通过
  817. result = await ctx.service.change.approvalSuccess(pid, ctx.request.body, changeData);
  818. break;
  819. // case 4:// 审批终止
  820. // result = await ctx.service.change.approvalStop(ctx.request.body);
  821. // break;
  822. case 5:// 审批退回到原报人
  823. result = await ctx.service.change.approvalCheckNo(pid, ctx.request.body, changeData);
  824. break;
  825. case 6:// 审批退回到上一个审批人
  826. result = await ctx.service.change.approvalCheckNoPre(pid, ctx.request.body, changeData);
  827. break;
  828. default:break;
  829. }
  830. if (!result) {
  831. throw '审批失败';
  832. }
  833. ctx.redirect(ctx.request.header.referer);
  834. } catch (err) {
  835. console.log(err);
  836. ctx.redirect(ctx.request.header.referer);
  837. }
  838. }
  839. /**
  840. * 收方单附件上传页
  841. * @param {Object} ctx - egg全局变量
  842. * @return {void}
  843. */
  844. async shoufangUpload(ctx) {
  845. try {
  846. const tid = parseInt(ctx.query.tid) || 0;
  847. const order = parseInt(ctx.query.order) || 0;
  848. const sfid = parseInt(ctx.query.sfid) || 0;
  849. if (!tid || !order || !sfid) {
  850. throw '参数有误';
  851. }
  852. const tender = await ctx.service.tender.getDataById(tid);
  853. if (!tender) {
  854. throw '该标段不存在';
  855. }
  856. const sfInfo = await ctx.service.stageShoufang.getDataByCondition({ id: sfid, tid, order });
  857. if (!sfInfo) {
  858. throw '该收方单不存在';
  859. }
  860. // 查找对应的台账或计量单元名称
  861. const ledger = await ctx.service.ledger.getData(tid);
  862. const ledgerInfo = ctx.helper._.find(ledger, { id: sfInfo.lid });
  863. let name = ledgerInfo.b_code;
  864. if (sfInfo.pid) {
  865. const pos = await ctx.service.pos.getPosData({ tid });
  866. const posInfo = ctx.helper._.find(pos, { lid: sfInfo.lid, id: sfInfo.pid });
  867. name += ' / ' + posInfo.name;
  868. }
  869. const renderData = {
  870. tender,
  871. order,
  872. name,
  873. sfid,
  874. whiteList: this.ctx.app.config.multipart.whitelist,
  875. };
  876. await ctx.render('wap/shoufangupload.ejs', renderData);
  877. } catch (error) {
  878. this.log(error);
  879. ctx.redirect('/wap/login');
  880. }
  881. }
  882. /**
  883. * 上传附件
  884. * @param {Object} ctx - egg全局变量
  885. * @return {void}
  886. */
  887. async shoufangUpFile(ctx) {
  888. const responseData = {
  889. err: 0,
  890. msg: '',
  891. data: [],
  892. };
  893. let stream;
  894. try {
  895. const parts = ctx.multipart({ autoFields: true });
  896. const files = [];
  897. let index = 0;
  898. while ((stream = await parts()) !== undefined) {
  899. // 判断是否存在
  900. const sfInfo = await ctx.service.stageShoufang.getDataById(parts.field.sfid);
  901. if (!sfInfo) {
  902. throw '该清单 / 计量单元下不存在收方单';
  903. }
  904. // 判断用户是否选择上传文件
  905. if (!stream.filename) {
  906. throw '请选择上传的文件!';
  907. }
  908. // const dirName = 'app/public/upload/stage/' + moment().format('YYYYMMDD');
  909. // 判断文件夹是否存在,不存在则直接创建文件夹
  910. // if (!fs.existsSync(path.join(this.app.baseDir, dirName))) {
  911. // await fs.mkdirSync(path.join(this.app.baseDir, dirName));
  912. // }
  913. const fileInfo = path.parse(stream.filename);
  914. const now_time = new Date();
  915. const create_time = Date.parse(now_time) / 1000;
  916. const filepath = `app/public/upload/${sfInfo.tid}/stage/shoufang/fujian_${create_time + index.toString() + fileInfo.ext}`;
  917. // await ctx.helper.saveStreamFile(stream, path.resolve(this.app.baseDir, filepath));
  918. await ctx.app.fujianOss.put(ctx.app.config.fujianOssFolder + filepath, stream);
  919. // console.log(await fs.existsSync(path.resolve(this.app.baseDir, 'app', filepath)));
  920. // const fileInfo = path.parse(stream.filename);
  921. // const fileName = 'stage' + create_time + '_' + index + fileInfo.ext;
  922. // 保存文件
  923. // await ctx.helper.saveStreamFile(stream, path.resolve(this.app.baseDir, dirName, fileName));
  924. if (stream) {
  925. await sendToWormhole(stream);
  926. }
  927. // 保存数据到att表
  928. const fileData = {
  929. tid: sfInfo.tid,
  930. sid: sfInfo.sid,
  931. sfid: sfInfo.id,
  932. in_time: now_time,
  933. filename: fileInfo.name,
  934. fileext: fileInfo.ext,
  935. filesize: Array.isArray(parts.field.size) ? parts.field.size[index] : parts.field.size,
  936. filepath,
  937. };
  938. // if (ctx.reUploadPermission) {
  939. // fileData.re_upload = 1;
  940. // }
  941. const result = await ctx.service.stageShoufangAtt.save(fileData);
  942. if (!result) {
  943. throw '导入数据库保存失败';
  944. }
  945. const attData = await ctx.service.stageShoufangAtt.getDataByFid(result.insertId);
  946. attData.in_time = moment(create_time * 1000).format('YYYY-MM-DD');
  947. files.length !== 0 ? files.unshift(attData) : files.push(attData);
  948. ++index;
  949. }
  950. responseData.data = files;
  951. } catch (err) {
  952. this.log(err);
  953. // 失败需要消耗掉stream 以防卡死
  954. if (stream) {
  955. await sendToWormhole(stream);
  956. }
  957. this.setMessage(err.toString(), this.messageType.ERROR);
  958. responseData.err = 1;
  959. responseData.msg = err.toString();
  960. }
  961. ctx.body = responseData;
  962. }
  963. /**
  964. * 删除附件
  965. * @param {Object} ctx - egg全局变量
  966. * @return {void}
  967. */
  968. async shoufangDeleteFile(ctx) {
  969. const responseData = {
  970. err: 0,
  971. msg: '',
  972. data: '',
  973. };
  974. try {
  975. const data = JSON.parse(ctx.request.body.data);
  976. const fileInfo = await ctx.service.stageShoufangAtt.getDataById(data.id);
  977. if (!fileInfo || !Object.keys(fileInfo).length) {
  978. throw '该文件不存在';
  979. }
  980. if (fileInfo !== undefined && fileInfo !== '') {
  981. // 先删除文件
  982. // await fs.unlinkSync(path.join(this.app.baseDir, fileInfo.filepath));
  983. await ctx.app.fujianOss.delete(ctx.app.config.fujianOssFolder + fileInfo.filepath);
  984. // 再删除数据库
  985. await ctx.service.stageShoufangAtt.deleteById(data.id);
  986. responseData.data = '';
  987. } else {
  988. throw '不存在该文件';
  989. }
  990. } catch (err) {
  991. responseData.err = 1;
  992. responseData.msg = err;
  993. }
  994. ctx.body = responseData;
  995. }
  996. /**
  997. * 编辑附件
  998. * @param {Object} ctx - egg全局变量
  999. * @return {void}
  1000. */
  1001. async shoufangEditFile(ctx) {
  1002. const responseData = {
  1003. err: 0,
  1004. msg: '',
  1005. data: '',
  1006. };
  1007. try {
  1008. const data = JSON.parse(ctx.request.body.data);
  1009. const fileInfo = await ctx.service.stageShoufangAtt.getDataById(data.id);
  1010. if (!fileInfo || !Object.keys(fileInfo).length) {
  1011. throw '该文件不存在';
  1012. }
  1013. await ctx.service.stageShoufangAtt.edit(data);
  1014. } catch (err) {
  1015. responseData.err = 1;
  1016. responseData.msg = err;
  1017. }
  1018. ctx.body = responseData;
  1019. }
  1020. /**
  1021. * 下载附件
  1022. * @param {Object} ctx - egg全局变量
  1023. * @return {void}
  1024. */
  1025. async messageDownloadFile(ctx) {
  1026. const id = ctx.params.fid;
  1027. if (id) {
  1028. try {
  1029. const fileInfo = await ctx.service.messageAtt.getDataById(id);
  1030. if (fileInfo !== undefined && fileInfo !== '') {
  1031. // const fileName = path.join(this.app.baseDir, fileInfo.filepath);
  1032. // 解决中文无法下载问题
  1033. const userAgent = (ctx.request.header['user-agent'] || '').toLowerCase();
  1034. let disposition = '';
  1035. if (userAgent.indexOf('msie') >= 0 || userAgent.indexOf('chrome') >= 0) {
  1036. disposition = 'attachment; filename=' + encodeURIComponent(fileInfo.filename + fileInfo.fileext);
  1037. } else if (userAgent.indexOf('firefox') >= 0) {
  1038. disposition = 'attachment; filename*="utf8\'\'' + encodeURIComponent(fileInfo.filename + fileInfo.fileext) + '"';
  1039. } else {
  1040. /* safari等其他非主流浏览器只能自求多福了 */
  1041. disposition = 'attachment; filename=' + new Buffer(fileInfo.filename + fileInfo.fileext).toString('binary');
  1042. }
  1043. ctx.response.set({
  1044. 'Content-Type': 'application/octet-stream',
  1045. 'Content-Disposition': disposition,
  1046. 'Content-Length': fileInfo.filesize,
  1047. });
  1048. // ctx.body = await fs.createReadStream(fileName);
  1049. ctx.body = await ctx.helper.ossFileGet(fileInfo.filepath);
  1050. } else {
  1051. throw '不存在该文件';
  1052. }
  1053. } catch (err) {
  1054. this.log(err);
  1055. this.setMessage(err.toString(), this.messageType.ERROR);
  1056. }
  1057. }
  1058. }
  1059. /**
  1060. * 下载附件
  1061. * @param {Object} ctx - egg全局变量
  1062. * @return {void}
  1063. */
  1064. async shoufangDownloadFile(ctx) {
  1065. const id = ctx.params.fid;
  1066. if (id) {
  1067. try {
  1068. const fileInfo = await ctx.service.stageShoufangAtt.getDataById(id);
  1069. if (fileInfo !== undefined && fileInfo !== '') {
  1070. // const fileName = path.join(this.app.baseDir, fileInfo.filepath);
  1071. // 解决中文无法下载问题
  1072. const userAgent = (ctx.request.header['user-agent'] || '').toLowerCase();
  1073. let disposition = '';
  1074. if (userAgent.indexOf('msie') >= 0 || userAgent.indexOf('chrome') >= 0) {
  1075. disposition = 'attachment; filename=' + encodeURIComponent(fileInfo.filename + fileInfo.fileext);
  1076. } else if (userAgent.indexOf('firefox') >= 0) {
  1077. disposition = 'attachment; filename*="utf8\'\'' + encodeURIComponent(fileInfo.filename + fileInfo.fileext) + '"';
  1078. } else {
  1079. /* safari等其他非主流浏览器只能自求多福了 */
  1080. disposition = 'attachment; filename=' + new Buffer(fileInfo.filename + fileInfo.fileext).toString('binary');
  1081. }
  1082. ctx.response.set({
  1083. 'Content-Type': 'application/octet-stream',
  1084. 'Content-Disposition': disposition,
  1085. 'Content-Length': fileInfo.filesize,
  1086. });
  1087. // ctx.body = await fs.createReadStream(fileName);
  1088. ctx.body = await ctx.helper.ossFileGet(fileInfo.filepath);
  1089. } else {
  1090. throw '不存在该文件';
  1091. }
  1092. } catch (err) {
  1093. this.log(err);
  1094. this.setMessage(err.toString(), this.messageType.ERROR);
  1095. }
  1096. }
  1097. }
  1098. async msg(ctx) {
  1099. try {
  1100. const msgId = parseInt(ctx.params.id) || 0;
  1101. if (!msgId) {
  1102. throw '参数有误';
  1103. }
  1104. const msgInfo = await ctx.service.message.getDataById(msgId);
  1105. const files = await ctx.service.messageAtt.getAtt(msgId);
  1106. if (!msgInfo) {
  1107. throw '项目通知不存在';
  1108. }
  1109. if (msgInfo && msgInfo.type === 1 && msgInfo.project_id !== ctx.session.sessionProject.id) {
  1110. throw '非该项目通知无权查看';
  1111. }
  1112. if (msgInfo) {
  1113. msgInfo.content = JSON.parse(JSON.stringify(msgInfo.content).replace(/\\r\\n/g, '<br>').replace(/\\"/g, '&#34;').replace(/'/g, '&#39;').replace(/\\t/g, '&#9;'));
  1114. }
  1115. const renderData = {
  1116. msgInfo,
  1117. moment,
  1118. files,
  1119. };
  1120. await ctx.render('wap/msg.ejs', renderData);
  1121. } catch (error) {
  1122. console.log(error);
  1123. this.log(error);
  1124. ctx.redirect('/wap/dashboard');
  1125. }
  1126. }
  1127. }
  1128. return WapController;
  1129. };