dashboard_controller.js 39 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660
  1. 'use strict';
  2. /**
  3. * 控制面板
  4. *
  5. * @author CaiAoLin
  6. * @date 2017/11/23
  7. * @version
  8. */
  9. const auditConst = require('../const/audit');
  10. const officeList = require('../const/cld_office').list;
  11. const maintainConst = require('../const/maintain');
  12. const typeColMap = require('../const/advance').typeColMap;
  13. const moment = require('moment');
  14. const fs = require('fs');
  15. const path = require('path');
  16. const sendToWormhole = require('stream-wormhole');
  17. module.exports = app => {
  18. class DashboardController extends app.BaseController {
  19. /**
  20. * 控制面板页面
  21. *
  22. * @param {Object} ctx - egg全局变量
  23. * @return {void}
  24. */
  25. async workspace(ctx) {
  26. const allAuditTenders = await ctx.service.ledgerAudit.getAuditTender(ctx.session.sessionUser.accountId);
  27. const allAuditStages = await ctx.service.stageAudit.getAuditStage(ctx.session.sessionUser.accountId);
  28. const allAuditChanges = await ctx.service.changeAudit.getAuditChange(ctx.session.sessionUser.accountId);
  29. const allAuditRevise = await ctx.service.reviseAudit.getAuditRevise(ctx.session.sessionUser.accountId);
  30. const allAuditMaterial = await ctx.service.materialAudit.getAuditMaterial(ctx.session.sessionUser.accountId);
  31. const allAuditAdvance = await ctx.service.advanceAudit.getAuditAdvance(ctx.session.sessionUser.accountId);
  32. const allAuditChangeProject = await ctx.service.changeProjectAudit.getAuditChangeProject(ctx.session.sessionUser.accountId);
  33. const allAuditChangeApply = await ctx.service.changeApplyAudit.getAuditChangeApply(ctx.session.sessionUser.accountId);
  34. const allAuditChangePlan = await ctx.service.changePlanAudit.getAuditChangePlan(ctx.session.sessionUser.accountId);
  35. const allAuditPayments = await ctx.service.paymentDetailAudit.getAuditPayment(ctx.session.sessionUser.accountId);
  36. const allAuditStageAss = await ctx.service.stageAuditAss.getAuditStageAss(ctx.session.sessionUser.accountId);
  37. const allAuditFinancials = await ctx.service.financialPayAudit.getAuditFinancial(ctx.session.sessionUser.accountId);
  38. const pa = await ctx.service.projectAccount.getDataById(ctx.session.sessionUser.accountId);
  39. const auditShenpiTenders = await ctx.service.ledgerAudit.getDonesByAudit(ctx.session.sessionUser.accountId);
  40. const auditShenpiStages = await ctx.service.stageAudit.getDonesByAudit(ctx.session.sessionUser.accountId);
  41. const auditShenpiChanges = await ctx.service.changeAudit.getDonesByAudit(ctx.session.sessionUser.accountId);
  42. const auditShenpiRevise = await ctx.service.reviseAudit.getDonesByAudit(ctx.session.sessionUser.accountId);
  43. const auditShenpiMaterial = await ctx.service.materialAudit.getDonesByAudit(ctx.session.sessionUser.accountId);
  44. const auditShenpiAdvance = await ctx.service.advanceAudit.getDonesByAudit(ctx.session.sessionUser.accountId);
  45. const auditShenpiChangeProject = await ctx.service.changeProjectAudit.getDonesByAudit(ctx.session.sessionUser.accountId);
  46. const auditShenpiChangeApply = await ctx.service.changeApplyAudit.getDonesByAudit(ctx.session.sessionUser.accountId);
  47. const auditShenpiChangePlan = await ctx.service.changePlanAudit.getDonesByAudit(ctx.session.sessionUser.accountId);
  48. const auditShenpiPayment = await ctx.service.paymentDetailAudit.getDonesByAudit(ctx.session.sessionUser.accountId);
  49. const auditShenpiFinancial = await ctx.service.financialPayAudit.getDonesByAudit(ctx.session.sessionUser.accountId);
  50. const dashboardStatus = {
  51. all: 0,
  52. dashboard: 0,
  53. worry: 0,
  54. early: 0,
  55. };
  56. let noticeList = [];
  57. // 还要考虑功能关闭不展示对应类型情况
  58. const subProjects = await ctx.service.subProject.getSubProject(ctx.session.sessionProject.id, ctx.session.sessionUser.accountId, ctx.session.sessionUser.is_admin, true);
  59. for (const subProject of subProjects) {
  60. subProject.page_show = ctx.service.subProject.getPageShow(subProject.page_show);
  61. const spTenders = ctx.helper._.filter(auditShenpiTenders, { spid: subProject.id });
  62. noticeList.push(...ctx.helper.addKeyValue4ObjArray(spTenders, 'shenpi_type', 'ledger'));
  63. const spStages = ctx.helper._.filter(auditShenpiStages, { spid: subProject.id });
  64. noticeList.push(...ctx.helper.addKeyValue4ObjArray(spStages, 'shenpi_type', 'stage'));
  65. const spChanges = ctx.helper._.filter(auditShenpiChanges, { spid: subProject.id });
  66. noticeList.push(...ctx.helper.addKeyValue4ObjArray(spChanges, 'shenpi_type', 'change'));
  67. const spRevise = ctx.helper._.filter(auditShenpiRevise, { spid: subProject.id });
  68. noticeList.push(...ctx.helper.addKeyValue4ObjArray(spRevise, 'shenpi_type', 'revise'));
  69. const spMaterial = subProject.page_show.openMaterial ? ctx.helper._.filter(auditShenpiMaterial, { spid: subProject.id }) : [];
  70. noticeList.push(...ctx.helper.addKeyValue4ObjArray(spMaterial, 'shenpi_type', 'material'));
  71. const spAdvance = ctx.helper._.filter(auditShenpiAdvance, { spid: subProject.id });
  72. noticeList.push(...ctx.helper.addKeyValue4ObjArray(spAdvance, 'shenpi_type', 'advance'));
  73. const spChangeProject = subProject.page_show.openChangeProject ? ctx.helper._.filter(auditShenpiChangeProject, { spid: subProject.id }) : [];
  74. noticeList.push(...ctx.helper.addKeyValue4ObjArray(spChangeProject, 'shenpi_type', 'changeProject'));
  75. const spChangeApply = subProject.page_show.openChangeApply ? ctx.helper._.filter(auditShenpiChangeApply, { spid: subProject.id }) : [];
  76. noticeList.push(...ctx.helper.addKeyValue4ObjArray(spChangeApply, 'shenpi_type', 'changeApply'));
  77. const spChangePlan = subProject.page_show.openChangePlan ? ctx.helper._.filter(auditShenpiChangePlan, { spid: subProject.id }) : [];
  78. noticeList.push(...ctx.helper.addKeyValue4ObjArray(spChangePlan, 'shenpi_type', 'changePlan'));
  79. const spPayment = subProject.page_show.openPayment ? ctx.helper._.filter(auditShenpiPayment, { spid: subProject.id }) : [];
  80. noticeList.push(...ctx.helper.addKeyValue4ObjArray(spPayment, 'shenpi_type', 'payment'));
  81. const spFinancial = subProject.page_show.openFinancial ? ctx.helper._.filter(auditShenpiFinancial, { spid: subProject.id }) : [];
  82. noticeList.push(...ctx.helper.addKeyValue4ObjArray(spFinancial, 'shenpi_type', 'financial'));
  83. }
  84. const noticeDayList = [];
  85. noticeList = ctx.helper._.orderBy(noticeList, ['shenpi_time'], ['desc']);
  86. for (const notice of noticeList) {
  87. const noticeDay = moment(new Date(notice.shenpi_time)).format('YYYY-MM-DD');
  88. if (noticeDayList.indexOf(noticeDay) === -1) noticeDayList.push(noticeDay);
  89. }
  90. // 审批时间状态提示,0:无预警,1,预警(当前时间大于创建时间常高于stageAuditEarly天时,触发提示),2,紧急(当前时间大于审批发起时常高于stageAuditWorry天时,触发提示)
  91. const auditTenders = await this.auditSet(ctx, allAuditTenders, subProjects, dashboardStatus, 'ledger');
  92. const auditStages = await this.auditSet(ctx, allAuditStages, subProjects, dashboardStatus, 'stage');
  93. const auditChanges = await this.auditSet(ctx, allAuditChanges, subProjects, dashboardStatus, 'change');
  94. const auditRevise = await this.auditSet(ctx, allAuditRevise, subProjects, dashboardStatus, 'revise');
  95. const auditMaterial = await this.auditSet(ctx, allAuditMaterial, subProjects, dashboardStatus, 'material');
  96. const auditAdvance = await this.auditSet(ctx, allAuditAdvance, subProjects, dashboardStatus, 'advance');
  97. const auditChangeProject = await this.auditSet(ctx, allAuditChangeProject, subProjects, dashboardStatus, 'changeProject');
  98. const auditChangeApply = await this.auditSet(ctx, allAuditChangeApply, subProjects, dashboardStatus, 'changeApply');
  99. const auditChangePlan = await this.auditSet(ctx, allAuditChangePlan, subProjects, dashboardStatus, 'changePlan');
  100. const auditPayments = await this.auditSet(ctx, allAuditPayments, subProjects, dashboardStatus, 'payment');
  101. const auditStageAss = await this.auditSet(ctx, allAuditStageAss, subProjects, dashboardStatus, 'stageAss');
  102. const auditFinancials = await this.auditSet(ctx, allAuditFinancials, subProjects, dashboardStatus, 'financial');
  103. const projectData = await ctx.service.project.getDataById(ctx.session.sessionProject.id);
  104. // 获取销售人员数据
  105. const salesmanData = await ctx.service.manager.getDataById(projectData.manager_id);
  106. const officeName = officeList[salesmanData.office];
  107. // 获取版本信息
  108. const versionList = await ctx.service.version.getAllDataByCondition({ orders: [['id', 'desc']], limit: 5, offset: 0 });
  109. // 获取项目通知
  110. const msgList = await ctx.service.message.getMsgList(ctx.session.sessionProject.id);
  111. // 获取系统通知
  112. const sysMsgList = await ctx.service.message.getMsgList(ctx.session.sessionProject.id, '', 1, 0, 2);
  113. // 获取系统维护信息
  114. const maintainData = await ctx.service.maintain.getDataById(1);
  115. const renderData = {
  116. auditTenders,
  117. auditStages,
  118. auditChanges,
  119. auditRevise,
  120. auditMaterial,
  121. auditAdvance,
  122. auditChangeProject,
  123. auditChangeApply,
  124. auditChangePlan,
  125. auditPayments,
  126. auditStageAss,
  127. auditFinancials,
  128. dashboardStatus,
  129. role: pa.role,
  130. authMobile: pa.auth_mobile,
  131. acLedger: auditConst.ledger,
  132. acStage: auditConst.stage,
  133. acChange: auditConst.change,
  134. acRevise: auditConst.revise,
  135. acMaterial: auditConst.material,
  136. acAdvance: auditConst.advance,
  137. acChangeProject: auditConst.changeProject,
  138. acChangeApply: auditConst.changeApply,
  139. acChangePlan: auditConst.changeApply,
  140. acFinancial: auditConst.financial,
  141. noticeList,
  142. noticeDayList,
  143. pushType: auditConst.pushType,
  144. projectData,
  145. salesmanData,
  146. officeName,
  147. versionList: JSON.parse(JSON.stringify(versionList).replace(/\\r\\n/g, '<br>').replace(/\\"/g, '&#34;').replace(/'/g, '&#39;').replace(/\\t/g, '&#9;')),
  148. msgList: JSON.parse(JSON.stringify(msgList).replace(/\\r\\n/g, '<br>').replace(/\\"/g, '&#34;').replace(/'/g, '&#39;').replace(/\\t/g, '&#9;')),
  149. sysMsgList: JSON.parse(JSON.stringify(sysMsgList).replace(/\\r\\n/g, '<br>').replace(/\\"/g, '&#34;').replace(/'/g, '&#39;').replace(/\\t/g, '&#9;')),
  150. uid: ctx.session.sessionUser.accountId,
  151. maintainData,
  152. maintainConst,
  153. typeColMap,
  154. jsFiles: this.app.jsFiles.common.concat(this.app.jsFiles.dashboard.workspace),
  155. };
  156. await this.layout('dashboard/workspace.ejs', renderData, 'dashboard/modal.ejs');
  157. await ctx.service.projectAccount.defaultUpdate({
  158. id: this.ctx.session.sessionUser.accountId,
  159. last_notice: new Date(),
  160. });
  161. }
  162. async loadTenders(ctx) {
  163. try {
  164. const responseData = { err: 0, msg: '', data: {} };
  165. const subProjects = await ctx.service.subProject.getSubProject(ctx.session.sessionProject.id, ctx.session.sessionUser.accountId, ctx.session.sessionUser.is_admin, true);
  166. const tenders = [];
  167. const accountInfo = await ctx.service.projectAccount.getDataById(ctx.session.sessionUser.accountId);
  168. const userPermission = accountInfo !== undefined && accountInfo.permission !== '' ? JSON.parse(accountInfo.permission) : null;
  169. for (const subProject of subProjects) {
  170. subProject.page_show = ctx.service.subProject.getPageShow(subProject.page_show);
  171. // 获取每个项目下参与的标段
  172. const subProjectTenders = await ctx.service.tender.getList('', userPermission, ctx.session.sessionUser.is_admin, '', subProject);
  173. tenders.push(...subProjectTenders);
  174. }
  175. for (const t of tenders) {
  176. // 用标段管理的方法获取t数据
  177. await this.ctx.service.tenderCache.loadTenderCache(t, '');
  178. t.total_price = t.ledger_tp && t.ledger_tp.total_price ? t.ledger_tp.total_price : 0;
  179. // [t.change_tp, t.change_p_tp, t.change_n_tp, t.change_valuation_tp, t.change_unvaluation_tp] = await ctx.service.change.getChangeTp(t.id);
  180. }
  181. responseData.data.tenderList = tenders;
  182. ctx.body = responseData;
  183. } catch (err) {
  184. this.log(err);
  185. ctx.body = { err: 1, msg: err.toString(), data: null };
  186. }
  187. }
  188. async auditSet(ctx, allAudits, subProjects, dashboardStatus, type) {
  189. const audits = [];
  190. for (const t of allAudits) {
  191. const sp = subProjects.find(sp => sp.id === t.spid);
  192. if (sp) {
  193. t.sp_name = sp.name;
  194. t.start_audit = 0;
  195. let calcTime;
  196. switch (type) {
  197. case 'ledger':
  198. calcTime = t.ledger_status === auditConst[type].status.checking ? t.begin_time : t.end_time;
  199. break;
  200. case 'revise':
  201. calcTime = t.status === auditConst[type].status.checking ? t.begin_time : t.end_time;
  202. break;
  203. case 'stage':
  204. calcTime = t.sstatus === auditConst[type].status.checkNo ? t.end_time : t.begin_time;
  205. break;
  206. case 'stageAss':
  207. calcTime = t.begin_time;
  208. break;
  209. case 'change':
  210. calcTime = t.begin_time ? t.begin_time : t.cin_time ? ctx.moment.unix(t.cin_time).format('YYYY/MM/DD HH:mm') : '';
  211. break;
  212. case 'changeProject':
  213. if (!sp.page_show.openChangeProject) return [];
  214. calcTime = t.status !== auditConst[type].status.back ? t.begin_time : t.end_time;
  215. break;
  216. case 'changeApply':
  217. if (!sp.page_show.openChangeApply) return [];
  218. calcTime = t.mstatus !== auditConst[type].status.checkNo ? t.begin_time : t.end_time;
  219. break;
  220. case 'changePlan':
  221. if (!sp.page_show.openChangePlan) return [];
  222. calcTime = t.mstatus !== auditConst[type].status.checkNo ? t.begin_time : t.end_time;
  223. break;
  224. case 'material':
  225. if (!sp.page_show.openMaterial) return [];
  226. calcTime = t.mstatus !== auditConst[type].status.checkNo ? t.begin_time : t.end_time;
  227. break;
  228. case 'advance':
  229. calcTime = t.mstatus !== auditConst[type].status.checkNo ? t.create_time : t.end_time;
  230. break;
  231. case 'payment':
  232. if (!sp.page_show.openPayment) return [];
  233. calcTime = t.sstatus !== auditConst.stage.status.checkNo ? t.begin_time : t.end_time;
  234. break;
  235. case 'financial':
  236. if (!sp.page_show.openFinancial) return [];
  237. calcTime = t.fpcstatus !== auditConst[type].status.checkNo ? t.begin_time : t.end_time;
  238. break;
  239. default:
  240. return [];
  241. }
  242. if (sp.page_show.openStageAudit) {
  243. const now = new Date();
  244. const calcDay = ctx.helper.calculateDaysBetween(now, calcTime);
  245. if (sp.page_show.stageAuditWorry && calcDay >= sp.page_show.stageAuditWorry) {
  246. t.start_audit = 2;
  247. dashboardStatus.worry += 1;
  248. } else if (sp.page_show.stageAuditEarly && calcDay >= sp.page_show.stageAuditEarly) {
  249. t.start_audit = 1;
  250. dashboardStatus.early += 1;
  251. }
  252. }
  253. dashboardStatus.dashboard += 1;
  254. audits.push(t);
  255. }
  256. }
  257. return audits;
  258. }
  259. /**
  260. * 控制面板页面
  261. *
  262. * @param {Object} ctx - egg全局变量
  263. * @return {void}
  264. */
  265. async index(ctx) {
  266. const auditTenders = await ctx.service.ledgerAudit.getAuditTender(ctx.session.sessionUser.accountId, ctx.subProject.id);
  267. const auditStages = await ctx.service.stageAudit.getAuditStage(ctx.session.sessionUser.accountId, ctx.subProject.id);
  268. const auditChanges = await ctx.service.changeAudit.getAuditChange(ctx.session.sessionUser.accountId, ctx.subProject.id);
  269. const auditRevise = await ctx.service.reviseAudit.getAuditRevise(ctx.session.sessionUser.accountId, ctx.subProject.id);
  270. const auditMaterial = ctx.subProject.page_show.openMaterial ? await ctx.service.materialAudit.getAuditMaterial(ctx.session.sessionUser.accountId, ctx.subProject.id) : [];
  271. const auditAdvance = await ctx.service.advanceAudit.getAuditAdvance(ctx.session.sessionUser.accountId, ctx.subProject.id);
  272. const auditChangeProject = ctx.subProject.page_show.openChangeProject ? await ctx.service.changeProjectAudit.getAuditChangeProject(ctx.session.sessionUser.accountId, ctx.subProject.id) : [];
  273. const auditChangeApply = ctx.subProject.page_show.openChangeApply ? await ctx.service.changeApplyAudit.getAuditChangeApply(ctx.session.sessionUser.accountId, ctx.subProject.id) : [];
  274. const auditChangePlan = ctx.subProject.page_show.openChangePlan ? await ctx.service.changePlanAudit.getAuditChangePlan(ctx.session.sessionUser.accountId, ctx.subProject.id) : [];
  275. const auditPayments = ctx.subProject.page_show.openPayment ? await ctx.service.paymentDetailAudit.getAuditPayment(ctx.session.sessionUser.accountId, ctx.subProject.id) : [];
  276. const auditStageAss = await ctx.service.stageAuditAss.getAuditStageAss(ctx.session.sessionUser.accountId, ctx.subProject.id);
  277. const auditFinancials = ctx.subProject.page_show.openFinancial ? await ctx.service.financialPayAudit.getAuditFinancial(ctx.session.sessionUser.accountId, ctx.subProject.id) : [];
  278. const pa = await ctx.service.projectAccount.getDataById(ctx.session.sessionUser.accountId);
  279. const noticeList = await ctx.service.noticePush.getNotice(ctx.session.sessionProject.id, pa.id, ctx.subProject.id);
  280. const projectData = await ctx.service.project.getDataById(ctx.session.sessionProject.id);
  281. // 获取销售人员数据
  282. const salesmanData = await ctx.service.manager.getDataById(projectData.manager_id);
  283. const officeName = officeList[salesmanData.office];
  284. // 获取版本信息
  285. const versionList = await ctx.service.version.getAllDataByCondition({ orders: [['id', 'desc']], limit: 5, offset: 0 });
  286. // 获取项目通知
  287. const msgList = await ctx.service.message.getMsgList(ctx.session.sessionProject.id, ctx.subProject.id);
  288. const userPermission = pa !== undefined && pa.permission !== '' ? JSON.parse(pa.permission) : null;
  289. const userMsgPermission = userPermission !== null && userPermission.project_msg !== undefined && parseInt(userPermission.project_msg) === 1;
  290. // 获取系统通知
  291. const sysMsgList = await ctx.service.message.getMsgList(ctx.session.sessionProject.id, '', 1, 0, 2);
  292. // 获取系统维护信息
  293. const maintainData = await ctx.service.maintain.getDataById(1);
  294. // 获取各个审批的次数及最后的审批时间
  295. const shenpi_count = [
  296. { count: await ctx.service.advanceAudit.getCountByChecked(ctx.session.sessionUser.accountId, ctx.subProject.id), name: '预付款' },
  297. { count: await ctx.service.ledgerAudit.getCountByChecked(ctx.session.sessionUser.accountId, ctx.subProject.id), name: '台账审批' },
  298. { count: await ctx.service.reviseAudit.getCountByChecked(ctx.session.sessionUser.accountId, ctx.subProject.id), name: '台账修订' },
  299. { count: await ctx.service.stageAudit.getCountByChecked(ctx.session.sessionUser.accountId, ctx.subProject.id), name: '计量审批' },
  300. { count: await ctx.service.changeAudit.getCountByChecked(ctx.session.sessionUser.accountId, ctx.subProject.id), name: '变更审批' },
  301. ];
  302. if (ctx.subProject.page_show.openChangeProject) shenpi_count.push({ count: await ctx.service.changeProjectAudit.getCountByChecked(ctx.session.sessionUser.accountId, ctx.subProject.id), name: '变更立项' });
  303. if (ctx.subProject.page_show.openChangeApply) shenpi_count.push({ count: await ctx.service.changeApplyAudit.getCountByChecked(ctx.session.sessionUser.accountId, ctx.subProject.id), name: '变更申请' });
  304. if (ctx.subProject.page_show.openChangePlan) shenpi_count.push({ count: await ctx.service.changePlanAudit.getCountByChecked(ctx.session.sessionUser.accountId, ctx.subProject.id), name: '变更方案' });
  305. if (ctx.subProject.page_show.openMaterial) shenpi_count.push({ count: await ctx.service.materialAudit.getCountByChecked(ctx.session.sessionUser.accountId, ctx.subProject.id), name: '材料调差' });
  306. if (ctx.subProject.page_show.openFinancial) shenpi_count.push({ count: await ctx.service.financialPayAudit.getCountByChecked(ctx.session.sessionUser.accountId, ctx.subProject.id), name: '资金支付' });
  307. // shenpi_count.push({ count: await ctx.service.advanceAudit.getCountByChecked(ctx.session.sessionUser.accountId), name: '预付款' });
  308. const total_count = ctx.app._.sumBy(shenpi_count, 'count');
  309. const shenpi_lastime = [
  310. await ctx.service.advanceAudit.getLastEndTimeByChecked(ctx.session.sessionUser.accountId, ctx.subProject.id),
  311. await ctx.service.ledgerAudit.getLastEndTimeByChecked(ctx.session.sessionUser.accountId, ctx.subProject.id),
  312. await ctx.service.reviseAudit.getLastEndTimeByChecked(ctx.session.sessionUser.accountId, ctx.subProject.id),
  313. await ctx.service.stageAudit.getLastEndTimeByChecked(ctx.session.sessionUser.accountId, ctx.subProject.id),
  314. await ctx.service.changeAudit.getLastEndTimeByChecked(ctx.session.sessionUser.accountId, ctx.subProject.id),
  315. ctx.subProject.page_show.openChangeProject ? await ctx.service.changeProjectAudit.getLastEndTimeByChecked(ctx.session.sessionUser.accountId, ctx.subProject.id) : null,
  316. ctx.subProject.page_show.openChangeApply ? await ctx.service.changeApplyAudit.getLastEndTimeByChecked(ctx.session.sessionUser.accountId, ctx.subProject.id) : null,
  317. ctx.subProject.page_show.openChangePlan ? await ctx.service.changePlanAudit.getLastEndTimeByChecked(ctx.session.sessionUser.accountId, ctx.subProject.id) : null,
  318. ctx.subProject.page_show.openMaterial ? await ctx.service.materialAudit.getLastEndTimeByChecked(ctx.session.sessionUser.accountId, ctx.subProject.id) : null,
  319. ctx.subProject.page_show.openFinancial ? await ctx.service.financialPayAudit.getLastEndTimeByChecked(ctx.session.sessionUser.accountId, ctx.subProject.id) : null,
  320. ];
  321. const last_time = ctx.app._.max(shenpi_lastime);
  322. // console.log(ctx.app._.max(shenpi_lastime), ctx.helper.calcDayNum(last_time));
  323. const renderData = {
  324. auditTenders,
  325. auditStages,
  326. auditChanges,
  327. auditRevise,
  328. auditMaterial,
  329. auditAdvance,
  330. auditChangeProject,
  331. auditChangeApply,
  332. auditChangePlan,
  333. auditPayments,
  334. auditStageAss,
  335. auditFinancials,
  336. shenpi_count,
  337. total_count,
  338. last_day: ctx.helper.calcDayNum(last_time),
  339. role: pa.role,
  340. authMobile: pa.auth_mobile,
  341. acLedger: auditConst.ledger,
  342. acStage: auditConst.stage,
  343. acChange: auditConst.change,
  344. acRevise: auditConst.revise,
  345. acMaterial: auditConst.material,
  346. acAdvance: auditConst.advance,
  347. acChangeProject: auditConst.changeProject,
  348. acChangeApply: auditConst.changeApply,
  349. acChangePlan: auditConst.changeApply,
  350. acFinancial: auditConst.financial,
  351. noticeList,
  352. pushType: auditConst.pushType,
  353. projectData,
  354. salesmanData,
  355. officeName,
  356. versionList: JSON.parse(JSON.stringify(versionList).replace(/\\r\\n/g, '<br>').replace(/\\"/g, '&#34;').replace(/'/g, '&#39;').replace(/\\t/g, '&#9;')),
  357. msgList: JSON.parse(JSON.stringify(msgList).replace(/\\r\\n/g, '<br>').replace(/\\"/g, '&#34;').replace(/'/g, '&#39;').replace(/\\t/g, '&#9;')),
  358. sysMsgList: JSON.parse(JSON.stringify(sysMsgList).replace(/\\r\\n/g, '<br>').replace(/\\"/g, '&#34;').replace(/'/g, '&#39;').replace(/\\t/g, '&#9;')),
  359. userMsgPermission,
  360. uid: ctx.session.sessionUser.accountId,
  361. maintainData,
  362. maintainConst,
  363. typeColMap,
  364. };
  365. await this.layout('dashboard/index.ejs', renderData, 'dashboard/modal.ejs');
  366. await ctx.service.projectAccount.defaultUpdate({
  367. id: this.ctx.session.sessionUser.accountId,
  368. last_notice: new Date(),
  369. });
  370. }
  371. /**
  372. * 控制面板-通知页面
  373. *
  374. * @param {Object} ctx - egg全局变量
  375. * @return {void}
  376. */
  377. async msg(ctx) {
  378. try {
  379. const page = ctx.page;
  380. const msgId = parseInt(ctx.params.mid) || 0;
  381. let msgInfo = msgId ? await ctx.service.message.getDataById(msgId) : null;
  382. const type = msgInfo ? msgInfo.type : ctx.request.query.type ? parseInt(ctx.request.query.type) : 1;
  383. if (msgInfo && msgInfo.type === 1 && msgInfo.project_id !== ctx.session.sessionProject.id) {
  384. throw '非该项目通知无权查看';
  385. }
  386. if (msgInfo) {
  387. msgInfo.content = JSON.parse(JSON.stringify(msgInfo.content).replace(/\\r\\n/g, '<br>').replace(/\\"/g, '&#34;').replace(/'/g, '&#39;').replace(/\\t/g, '&#9;'));
  388. msgInfo.files = await this.ctx.service.messageAtt.getAtt(msgInfo.id);
  389. }
  390. const total = type === 1 ?
  391. await ctx.service.message.count({ project_id: ctx.session.sessionProject.id, spid: [ctx.subProject.id, ''], type }) :
  392. await ctx.service.message.count({ status: 1, type });
  393. const limit = 5;
  394. const offset = limit * (this.ctx.page - 1);
  395. const msgList = await ctx.service.message.getMsgList(ctx.session.sessionProject.id, ctx.subProject.id, limit, offset, type);
  396. const pa = await ctx.service.projectAccount.getDataById(ctx.session.sessionUser.accountId);
  397. const userPermission = pa !== undefined && pa.permission !== '' ? JSON.parse(pa.permission) : null;
  398. const userMsgPermission = userPermission !== null && userPermission.project_msg !== undefined && parseInt(userPermission.project_msg) === 1;
  399. if (!msgInfo) {
  400. msgInfo = msgList[0];
  401. }
  402. // 分页相关
  403. const pageInfo = {
  404. page,
  405. total: Math.ceil(total / limit),
  406. queryData: JSON.stringify(ctx.urlInfo.query),
  407. };
  408. const renderData = {
  409. msgInfo,
  410. uid: ctx.session.sessionUser.accountId,
  411. type,
  412. pageInfo,
  413. userMsgPermission,
  414. msgList: JSON.parse(JSON.stringify(msgList).replace(/\\r\\n/g, '<br>').replace(/\\"/g, '&#34;').replace(/'/g, '&#39;').replace(/\\t/g, '&#9;')),
  415. };
  416. await this.layout('dashboard/msg.ejs', renderData);
  417. } catch (error) {
  418. console.log(error);
  419. this.log(error);
  420. ctx.session.postError = error.toString();
  421. ctx.redirect('/sp/' + ctx.subProject.id + '/dashboard');
  422. }
  423. }
  424. /**
  425. * 控制面板-通知添加和编辑页面
  426. *
  427. * @param {Object} ctx - egg全局变量
  428. * @return {void}
  429. */
  430. async msgAdd(ctx) {
  431. let id = ctx.params.mid;
  432. id = parseInt(id);
  433. try {
  434. if (isNaN(id) || id < 0) {
  435. throw '参数错误';
  436. }
  437. const rule = ctx.service.message.rule();
  438. const jsValidator = await this.jsValidator.convert(rule).build();
  439. const msgInfo = id === 0 ? {} : await ctx.service.message.getDataById(id);
  440. const files = await ctx.service.messageAtt.getAtt(id);
  441. const renderData = {
  442. jsValidator,
  443. msgInfo,
  444. files,
  445. whiteList: ctx.app.config.multipart.whitelist,
  446. moment,
  447. };
  448. await this.layout('dashboard/msg_add.ejs', renderData, 'dashboard/msg_modal.ejs');
  449. } catch (error) {
  450. console.log(error);
  451. // this.setMessage(error.toString(), this.messageType.ERROR);
  452. ctx.redirect(ctx.request.header.referer);
  453. }
  454. }
  455. /**
  456. * 控制面板-通知保存
  457. *
  458. * @param {Object} ctx - egg全局变量
  459. * @return {void}
  460. */
  461. async msgSet(ctx) {
  462. try {
  463. let id = ctx.params.mid;
  464. id = parseInt(id);
  465. if (isNaN(id) || id < 0) {
  466. throw '参数错误';
  467. }
  468. const rule = ctx.service.message.rule();
  469. ctx.helper.validate(rule);
  470. const result = await ctx.service.message.save(id, ctx.request.body, ctx.session.sessionUser, ctx.session.sessionProject.id, ctx.subProject.id);
  471. if (result) {
  472. // 新增的项目通知会发送微信模版消息通知客户
  473. if (id === 0) {
  474. // 获取该项目所有的openid,发送信息
  475. const wechats = await ctx.service.projectAccount.getOpenIdListByPid(ctx.session.sessionProject.id);
  476. if (wechats.length > 0) {
  477. const msgInfo = await ctx.service.message.getDataById(result);
  478. const projectData = await ctx.service.project.getDataById(ctx.session.sessionProject.id);
  479. // 绑定成功通知
  480. const templateId = 'VKUo4us4lt2dQY0EaaJxcui2jkjmriN3A0K7i4kpZwY';
  481. const url = ctx.protocol + '://' + ctx.host + '/wx/url2wap?project=' + ctx.session.sessionProject.code + '&url=' + ctx.protocol + '://' + ctx.host + '/wap/dashboard/msg/' + msgInfo.id;
  482. const msgData = {
  483. thing21: {
  484. value: ctx.helper.contentChange(projectData.name),
  485. },
  486. thing2: {
  487. value: ctx.helper.contentChange(msgInfo.title),
  488. },
  489. thing8: {
  490. value: msgInfo.creator,
  491. },
  492. time3: {
  493. value: moment(msgInfo.release_time * 1000).format('YYYY-MM-DD'),
  494. },
  495. };
  496. for (const wx of wechats) {
  497. const result = await app.wechat.api.sendTemplate(wx.wx_openid, templateId, url, '', msgData);
  498. }
  499. }
  500. }
  501. ctx.redirect('/sp/' + ctx.subProject.id + '/dashboard/msg');
  502. }
  503. } catch (error) {
  504. console.log(error);
  505. ctx.redirect(ctx.request.header.referer);
  506. }
  507. }
  508. /**
  509. * 控制面板-通知删除
  510. *
  511. * @param {Object} ctx - egg全局变量
  512. * @return {void}
  513. */
  514. async msgDelete(ctx) {
  515. try {
  516. let id = ctx.params.mid;
  517. id = parseInt(id);
  518. if (isNaN(id) || id <= 0) {
  519. throw '参数错误';
  520. }
  521. const msgInfo = await ctx.service.message.getDataById(id);
  522. if (!msgInfo || msgInfo.create_uid !== ctx.session.sessionUser.accountId) {
  523. throw '通知不存在或无权限操作';
  524. }
  525. const result = await ctx.service.message.deleteMsg(msgInfo.id);
  526. if (result) {
  527. ctx.redirect('/sp/' + ctx.subProject.id + '/dashboard/msg');
  528. }
  529. } catch (error) {
  530. console.log(error);
  531. ctx.redirect(ctx.request.header.referer);
  532. }
  533. }
  534. /**
  535. * 将推送记录设置为已读
  536. * @param {Object} ctx 上下文
  537. */
  538. async pushSet(ctx) {
  539. try {
  540. const { id } = JSON.parse(ctx.request.body.data);
  541. const data = await ctx.service.noticePush.set(id);
  542. ctx.body = { err: 0, msg: '' };
  543. } catch (err) {
  544. this.log(err);
  545. ctx.body = { err: 1, msg: err.toString(), data: null };
  546. }
  547. }
  548. /**
  549. * 上传附件
  550. * @param {*} ctx 上下文
  551. */
  552. async msgUploadFile(ctx) {
  553. let stream;
  554. try {
  555. const responseData = { err: 0, msg: '', data: {} };
  556. const mid = ctx.params.mid || 0;
  557. if (!mid) throw '参数有误';
  558. const parts = this.ctx.multipart({
  559. autoFields: true,
  560. });
  561. const files = [];
  562. const create_time = Date.parse(new Date()) / 1000;
  563. let idx = 0;
  564. while ((stream = await parts()) !== undefined) {
  565. if (!stream.filename) {
  566. // 如果没有传入直接返回
  567. return;
  568. }
  569. const fileInfo = path.parse(stream.filename);
  570. const filepath = `app/public/upload/message/fujian_${create_time + idx.toString() + fileInfo.ext}`;
  571. await ctx.app.fujianOss.put(ctx.app.config.fujianOssFolder + filepath, stream);
  572. files.push({ filepath, name: stream.filename, ext: fileInfo.ext });
  573. ++idx;
  574. stream && (await sendToWormhole(stream));
  575. }
  576. const in_time = new Date();
  577. const payload = files.map(file => {
  578. let idx;
  579. if (Array.isArray(parts.field.name)) {
  580. idx = parts.field.name.findIndex(name => name === file.name);
  581. } else {
  582. idx = 'isString';
  583. }
  584. const newFile = {
  585. project_id: ctx.session.sessionProject.id,
  586. mid,
  587. uid: ctx.session.sessionUser.accountId,
  588. filename: file.name,
  589. fileext: file.ext,
  590. filesize: ctx.helper.bytesToSize(idx === 'isString' ? parts.field.size : parts.field.size[idx]),
  591. filepath: file.filepath,
  592. upload_time: in_time,
  593. };
  594. return newFile;
  595. });
  596. // 执行文件信息写入数据库
  597. await ctx.service.messageAtt.saveFileMsgToDb(payload);
  598. // 将最新的当前标段的所有文件信息返回
  599. responseData.data = await ctx.service.messageAtt.getAtt(mid);
  600. ctx.body = responseData;
  601. } catch (err) {
  602. stream && (await sendToWormhole(stream));
  603. this.log(err);
  604. ctx.body = { err: 1, msg: err.toString(), data: null };
  605. }
  606. }
  607. /**
  608. * 删除附件
  609. * @param {Ojbect} ctx 上下文
  610. */
  611. async msgDeleteFile(ctx) {
  612. try {
  613. const mid = ctx.params.mid || 0;
  614. const responseData = { err: 0, msg: '', data: {} };
  615. const data = JSON.parse(ctx.request.body.data);
  616. const fileInfo = await ctx.service.messageAtt.getDataById(data.id);
  617. if (fileInfo) {
  618. // 先删除文件
  619. // await fs.unlinkSync(path.resolve(this.app.baseDir, './app', fileInfo.filepath));
  620. await ctx.app.fujianOss.delete(ctx.app.config.fujianOssFolder + fileInfo.filepath);
  621. // 再删除数据库
  622. await ctx.service.messageAtt.delete(data.id);
  623. } else {
  624. throw '不存在该文件';
  625. }
  626. responseData.data = await ctx.service.messageAtt.getAtt(mid);
  627. ctx.body = responseData;
  628. } catch (err) {
  629. this.log(err);
  630. ctx.body = { err: 1, msg: err.toString(), data: null };
  631. }
  632. }
  633. }
  634. return DashboardController;
  635. };