feat: 모바일 신고 시스템 구축 + tkqc 연동 + tkuser 이슈유형 관리
- tkreport 모바일 신고 페이지 (5단계 위자드: 유형→위치→프로젝트→항목→사진) - 프로젝트 DB 연동 (아코디언 UI: TBM등록/활성프로젝트/모름) - 클라이언트 이미지 리사이징 (1280px, JPEG 80%) - nginx client_max_body_size 50m, /api/projects/ 프록시 추가 - 부적합 신고 → tkqc 자동 연동 (사진 base64 전달, SSO 토큰 유지) - work_issue_reports에 project_id 컬럼 추가 - imageUploadService 경로 수정 (public/uploads → uploads, Docker 볼륨 일치) - tkuser 이슈유형 탭, 휴가관리, nginx 프록시 업데이트 - tkqc 대시보드/수신함/관리함/폐기함 UI 업데이트 - system1 랜딩페이지 업데이트 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -208,6 +208,7 @@ exports.createReport = async (req, res) => {
|
||||
issue_category_id,
|
||||
issue_item_id,
|
||||
custom_item_name, // 직접 입력한 항목명
|
||||
project_id,
|
||||
additional_description,
|
||||
photos = []
|
||||
} = req.body;
|
||||
@@ -275,6 +276,7 @@ exports.createReport = async (req, res) => {
|
||||
reporter_id,
|
||||
factory_category_id: factory_category_id || null,
|
||||
workplace_id: workplace_id || null,
|
||||
project_id: project_id || null,
|
||||
custom_location: custom_location || null,
|
||||
tbm_session_id: tbm_session_id || null,
|
||||
visit_request_id: visit_request_id || null,
|
||||
@@ -306,23 +308,35 @@ exports.createReport = async (req, res) => {
|
||||
});
|
||||
|
||||
if (categoryInfo && categoryInfo.category_type === 'nonconformity') {
|
||||
// 사진은 System 2에만 저장, URL 참조만 전달
|
||||
const baseUrl = process.env.SYSTEM2_PUBLIC_URL || 'https://tkreport.technicalkorea.net';
|
||||
const photoUrls = Object.values(photoPaths).filter(Boolean)
|
||||
.map(p => `${baseUrl}/api/uploads/${p}`);
|
||||
|
||||
const descParts = [additional_description || categoryInfo.category_name];
|
||||
if (photoUrls.length > 0) {
|
||||
descParts.push('', '[첨부 사진]');
|
||||
photoUrls.forEach((url, i) => descParts.push(`${i + 1}. ${url}`));
|
||||
// 저장된 사진 파일을 base64로 읽어서 System 3에 전달
|
||||
const fs = require('fs').promises;
|
||||
const path = require('path');
|
||||
const photoBase64List = [];
|
||||
for (const p of Object.values(photoPaths)) {
|
||||
if (!p) continue;
|
||||
try {
|
||||
const filePath = path.join(__dirname, '..', p);
|
||||
const buf = await fs.readFile(filePath);
|
||||
const b64 = `data:image/jpeg;base64,${buf.toString('base64')}`;
|
||||
photoBase64List.push(b64);
|
||||
} catch (readErr) {
|
||||
console.error('사진 파일 읽기 실패:', p, readErr.message);
|
||||
}
|
||||
}
|
||||
|
||||
const descText = additional_description || categoryInfo.category_name;
|
||||
|
||||
// 원래 신고자의 SSO 토큰 추출
|
||||
const originalToken = (req.headers['authorization'] || '').replace('Bearer ', '');
|
||||
|
||||
const result = await mProjectService.sendToMProject({
|
||||
category: categoryInfo.category_name,
|
||||
description: descParts.join('\n'),
|
||||
description: descText,
|
||||
reporter_name: req.user.name || req.user.username,
|
||||
tk_issue_id: reportId,
|
||||
photos: [] // 사진 복사 안 함 (URL 참조만)
|
||||
project_id: project_id || null,
|
||||
photos: photoBase64List,
|
||||
ssoToken: originalToken
|
||||
});
|
||||
if (result.success && result.mProjectId) {
|
||||
workIssueModel.updateMProjectId(reportId, result.mProjectId, () => {});
|
||||
|
||||
Reference in New Issue
Block a user