feat: 설비 관리 시스템 구축

## 주요 기능
- 설비 등록/수정/삭제 기능
- 작업장별 설비 연결
- 작업장 지도에서 설비 위치 정의
- 필터링 및 검색 기능

## 백엔드
- equipments 테이블 생성 (마이그레이션)
- 설비 API (모델, 컨트롤러, 라우트) 구현
- workplaces 테이블에 layout_image 컬럼 추가

## 프론트엔드
- 설비 관리 페이지 (equipments.html)
- 설비 관리 JavaScript (equipment-management.js)
- 작업장 지도 모달 개선

## 버그 수정
- 카테고리/작업장 이미지 보존 로직 개선 (null 처리)
- 작업장 레이아웃 이미지 업로드 경로 수정 (public/uploads → uploads)

🤖 Generated with Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Hyungi Ahn
2026-01-28 09:22:57 +09:00
parent 9c98c44d8a
commit e1227a69fe
13 changed files with 2710 additions and 22 deletions

View File

@@ -0,0 +1,36 @@
// routes/equipmentRoutes.js
const express = require('express');
const router = express.Router();
const equipmentController = require('../controllers/equipmentController');
// ==================== 설비 관리 ====================
// CREATE 설비
router.post('/', equipmentController.createEquipment);
// READ ALL 설비 (쿼리 파라미터로 필터링 가능)
// ?workplace_id=1&equipment_type=CNC&status=active&search=설비명
router.get('/', equipmentController.getAllEquipments);
// READ ACTIVE 설비
router.get('/active/list', equipmentController.getActiveEquipments);
// READ 설비 유형 목록
router.get('/types', equipmentController.getEquipmentTypes);
// READ 작업장별 설비
router.get('/workplace/:workplaceId', equipmentController.getEquipmentsByWorkplace);
// READ ONE 설비
router.get('/:id', equipmentController.getEquipmentById);
// UPDATE 설비
router.put('/:id', equipmentController.updateEquipment);
// UPDATE 설비 지도 위치
router.patch('/:id/map-position', equipmentController.updateMapPosition);
// DELETE 설비
router.delete('/:id', equipmentController.deleteEquipment);
module.exports = router;

View File

@@ -1,8 +1,36 @@
// routes/workplaceRoutes.js
const express = require('express');
const router = express.Router();
const multer = require('multer');
const path = require('path');
const workplaceController = require('../controllers/workplaceController');
// Multer 설정 - 작업장 레이아웃 이미지 업로드
const storage = multer.diskStorage({
destination: (req, file, cb) => {
cb(null, path.join(__dirname, '../uploads'));
},
filename: (req, file, cb) => {
const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1E9);
cb(null, 'workplace-layout-' + uniqueSuffix + path.extname(file.originalname));
}
});
const upload = multer({
storage,
fileFilter: (req, file, cb) => {
const allowedTypes = /jpeg|jpg|png|gif/;
const extname = allowedTypes.test(path.extname(file.originalname).toLowerCase());
const mimetype = allowedTypes.test(file.mimetype);
if (mimetype && extname) {
return cb(null, true);
} else {
cb(new Error('이미지 파일만 업로드 가능합니다 (jpeg, jpg, png, gif)'));
}
},
limits: { fileSize: 5 * 1024 * 1024 } // 5MB 제한
});
// ==================== 카테고리(공장) 관리 ====================
// CREATE 카테고리
@@ -43,4 +71,27 @@ router.put('/:id', workplaceController.updateWorkplace);
// DELETE 작업장
router.delete('/:id', workplaceController.deleteWorkplace);
// ==================== 작업장 지도 영역 관리 ====================
// 카테고리 레이아웃 이미지 업로드
router.post('/categories/:id/layout-image', upload.single('image'), workplaceController.uploadCategoryLayoutImage);
// 작업장 레이아웃 이미지 업로드
router.post('/:id/layout-image', upload.single('image'), workplaceController.uploadWorkplaceLayoutImage);
// CREATE 지도 영역
router.post('/map-regions', workplaceController.createMapRegion);
// READ 카테고리별 지도 영역
router.get('/categories/:categoryId/map-regions', workplaceController.getMapRegionsByCategory);
// READ 작업장별 지도 영역
router.get('/map-regions/workplace/:workplaceId', workplaceController.getMapRegionByWorkplace);
// UPDATE 지도 영역
router.put('/map-regions/:id', workplaceController.updateMapRegion);
// DELETE 지도 영역
router.delete('/map-regions/:id', workplaceController.deleteMapRegion);
module.exports = router;