| 
					
				 | 
			
			
				@@ -12,6 +12,8 @@ const auditConst = require('../const/audit').stage; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 const spreadSetting = require('../lib/spread_setting'); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 const measureType = require('../const/tender').measureType; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 const tenderConst = require('../const/tender'); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+const sendToWormhole = require('stream-wormhole'); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+const path = require('path'); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 module.exports = app => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -154,6 +156,7 @@ module.exports = app => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         async load(ctx) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             try { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 const relaStage = await this.ctx.service.stageRela.getDataById(ctx.params.trid); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                const stage = await this.ctx.service.stage.getDataById(relaStage.rela_sid); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 const data = JSON.parse(ctx.request.body.data); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 const filter = data.filter.split(';'); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 const responseData = { err: 0, msg: '', data: {} }; 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -167,6 +170,7 @@ module.exports = app => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                             break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                         case 'detail': 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                             responseData.data.detailData = await ctx.service.stageDetail.getLastestStageData(relaStage.rela_tid, relaStage.rela_sid); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            responseData.data.detailAtt = await this.ctx.service.stageDetailAtt.getStageData(relaStage.rela_sid, stage.im_type); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                             break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                         case 'change': 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                             responseData.data.changeData = await ctx.service.stageChange.getLastestAllStageData(relaStage.rela_tid, relaStage.rela_sid); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -185,6 +189,104 @@ module.exports = app => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 ctx.body = { err: 1, msg: err.toString(), data: null }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        async uploadImFile(ctx) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            let stream; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            try { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                const relaStage = await this.ctx.service.stageRela.getDataById(ctx.params.trid); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                const stage = await this.ctx.service.stage.getDataById(relaStage.rela_sid); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                const parts = ctx.multipart({ autoFields: true }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                let index = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                const create_time = Date.parse(new Date()) / 1000; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                stream = await parts(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                const uploadFiles = []; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                while (stream !== undefined) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    if (!stream.filename) throw '未发现上传文件!'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    const fileInfo = path.parse(stream.filename); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    const dirName = path.join('app', 'public', 'upload', relaStage.tid.toString(), 'im'); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    const fileName = `${ctx.session.sessionUser.accountId}_${create_time}_${index}${fileInfo.ext}`; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    // 保存文件 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    await ctx.helper.saveStreamFile(stream, path.join(this.app.baseDir, dirName, fileName)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    await sendToWormhole(stream); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    // 插入到stage_pay对应的附件列表中 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    uploadFiles.push({ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        file_id: this.ctx.app.uuid.v4(), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        filename: fileInfo.name, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        fileext: fileInfo.ext, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        filesize: Array.isArray(parts.field.size) ? parts.field.size[index] : parts.field.size, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        filepath: path.join(dirName, fileName), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        uid: ctx.session.sessionUser.accountId, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        in_time: ctx.moment(create_time * 1000).format('YYYY-MM-DD'), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        renew: true, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    ++index; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    if (Array.isArray(parts.field.size) && index < parts.field.size.length) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        stream = await parts(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        stream = undefined; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                const baseInfo = JSON.parse(parts.field.base); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                const result = await ctx.service.stageDetailAtt.addFiles(stage, baseInfo, uploadFiles); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                ctx.body = { err: 0, mgs: '', data: result }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } catch (err) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                console.log(err); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                // 失败需要消耗掉stream 以防卡死 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                if (stream) await sendToWormhole(stream); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                ctx.log(err); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                ctx.ajaxErrorBody(err, '上传附件失败'); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        async deleteImFile(ctx) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            try { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                const data = JSON.parse(ctx.request.body.data); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                if (!data.uuid || !data.file_id) throw '数据错误'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                const result = await ctx.service.stageDetailAtt.delFiles(data.uuid, data.file_id); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                ctx.body = { err: 0, msg: '', data: result }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } catch (err) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                ctx.log(err); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                ctx.ajaxErrorBody(err, '删除附件失败'); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        async downloadImFile(ctx) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            try { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                const uuid = ctx.query.im_id; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                const file_id = ctx.query.file_id; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                if (!uuid || !file_id) throw '数据错误'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                const fileInfo = await ctx.service.stageDetailAtt.getFiles(uuid, file_id); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                if (!fileInfo) throw '文件不存在'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                const fileName = path.join(this.app.baseDir, fileInfo.filepath); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                // 解决中文无法下载问题 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                const userAgent = (ctx.request.header['user-agent'] || '').toLowerCase(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                let disposition = ''; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                if (userAgent.indexOf('msie') >= 0 || userAgent.indexOf('chrome') >= 0) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    disposition = 'attachment; filename=' + encodeURIComponent(fileInfo.filename + fileInfo.fileext); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                } else if (userAgent.indexOf('firefox') >= 0) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    disposition = 'attachment; filename*="utf8\'\'' + encodeURIComponent(fileInfo.filename + fileInfo.fileext) + '"'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    /* safari等其他非主流浏览器只能自求多福了 */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    disposition = 'attachment; filename=' + new Buffer(fileInfo.filename + fileInfo.fileext).toString('binary'); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                ctx.response.set({ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    'Content-Type': 'application/octet-stream', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    'Content-Disposition': disposition, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    'Content-Length': fileInfo.filesize, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                ctx.body = await fs.createReadStream(fileName); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } catch (err) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                ctx.log(err); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                ctx.postError(err, '下载文件失败'); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 |