154 lines
4.6 KiB
JavaScript
154 lines
4.6 KiB
JavaScript
const http = require('http');
|
||
const fs = require('fs');
|
||
const path = require('path');
|
||
|
||
const PORT = process.env.PORT || 3000;
|
||
const DATA_FILE = path.join(__dirname, 'data.json');
|
||
|
||
function load() {
|
||
try {
|
||
return JSON.parse(fs.readFileSync(DATA_FILE, 'utf8'));
|
||
} catch {
|
||
return { items: [], log: [] };
|
||
}
|
||
}
|
||
|
||
function save(data) {
|
||
fs.writeFileSync(DATA_FILE, JSON.stringify(data, null, 2));
|
||
}
|
||
|
||
const server = http.createServer((req, res) => {
|
||
const url = req.url.split('?')[0];
|
||
const method = req.method;
|
||
|
||
res.setHeader('Access-Control-Allow-Origin', '*');
|
||
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');
|
||
res.setHeader('Access-Control-Allow-Headers', 'Content-Type');
|
||
|
||
if (method === 'OPTIONS') {
|
||
res.writeHead(204);
|
||
res.end();
|
||
return;
|
||
}
|
||
|
||
if (url === '/api/requests' && method === 'GET') {
|
||
const data = load();
|
||
res.writeHead(200, { 'Content-Type': 'application/json' });
|
||
res.end(JSON.stringify(data.items));
|
||
return;
|
||
}
|
||
|
||
if (url === '/api/requests' && method === 'POST') {
|
||
let body = '';
|
||
req.on('data', chunk => { body += chunk; });
|
||
req.on('end', () => {
|
||
const data = load();
|
||
const newRequest = JSON.parse(body);
|
||
newRequest.id = Date.now();
|
||
newRequest.createdAt = new Date().toISOString();
|
||
newRequest.updatedAt = new Date().toISOString();
|
||
data.items.push(newRequest);
|
||
data.log.push({
|
||
when: new Date().toISOString(),
|
||
what: `Создана заявка #${newRequest.id}`,
|
||
who: newRequest.operator || 'Система'
|
||
});
|
||
save(data);
|
||
res.writeHead(201, { 'Content-Type': 'application/json' });
|
||
res.end(JSON.stringify(newRequest));
|
||
});
|
||
return;
|
||
}
|
||
|
||
if (url === '/api/requests' && method === 'PUT') {
|
||
let body = '';
|
||
req.on('data', chunk => { body += chunk; });
|
||
req.on('end', () => {
|
||
const data = load();
|
||
const updated = JSON.parse(body);
|
||
const index = data.items.findIndex(r => r.id === updated.id);
|
||
if (index !== -1) {
|
||
const old = data.items[index];
|
||
updated.updatedAt = new Date().toISOString();
|
||
data.items[index] = { ...old, ...updated };
|
||
data.log.push({
|
||
when: new Date().toISOString(),
|
||
what: `Обновлена заявка #${updated.id}: статус ${old.status} → ${updated.status}`,
|
||
who: updated.operator || 'Система'
|
||
});
|
||
save(data);
|
||
res.writeHead(200, { 'Content-Type': 'application/json' });
|
||
res.end(JSON.stringify(updated));
|
||
} else {
|
||
res.writeHead(404, { 'Content-Type': 'application/json' });
|
||
res.end(JSON.stringify({ error: 'Заявка не найдена' }));
|
||
}
|
||
});
|
||
return;
|
||
}
|
||
|
||
if (url.startsWith('/api/requests/') && method === 'DELETE') {
|
||
const id = parseInt(url.split('/').pop());
|
||
const data = load();
|
||
const index = data.items.findIndex(r => r.id === id);
|
||
if (index !== -1) {
|
||
const removed = data.items.splice(index, 1)[0];
|
||
data.log.push({
|
||
when: new Date().toISOString(),
|
||
what: `Удалена заявка #${id}`,
|
||
who: 'Оператор'
|
||
});
|
||
save(data);
|
||
res.writeHead(200, { 'Content-Type': 'application/json' });
|
||
res.end(JSON.stringify(removed));
|
||
} else {
|
||
res.writeHead(404, { 'Content-Type': 'application/json' });
|
||
res.end(JSON.stringify({ error: 'Заявка не найдена' }));
|
||
}
|
||
return;
|
||
}
|
||
|
||
if (url === '/api/log' && method === 'GET') {
|
||
const data = load();
|
||
res.writeHead(200, { 'Content-Type': 'application/json' });
|
||
res.end(JSON.stringify(data.log.slice(-50)));
|
||
return;
|
||
}
|
||
|
||
if (url === '/' || url === '/index.html') {
|
||
const filePath = path.join(__dirname, 'index.html');
|
||
fs.readFile(filePath, 'utf8', (err, content) => {
|
||
if (err) {
|
||
res.writeHead(500);
|
||
res.end('Ошибка загрузки страницы');
|
||
return;
|
||
}
|
||
res.writeHead(200, { 'Content-Type': 'text/html' });
|
||
res.end(content);
|
||
});
|
||
return;
|
||
}
|
||
|
||
const filePath = path.join(__dirname, url);
|
||
fs.readFile(filePath, (err, content) => {
|
||
if (err) {
|
||
res.writeHead(404);
|
||
res.end('Не найдено');
|
||
return;
|
||
}
|
||
const ext = path.extname(url);
|
||
const mime = {
|
||
'.css': 'text/css',
|
||
'.js': 'application/javascript',
|
||
'.png': 'image/png',
|
||
'.svg': 'image/svg+xml'
|
||
};
|
||
res.writeHead(200, { 'Content-Type': mime[ext] || 'text/plain' });
|
||
res.end(content);
|
||
});
|
||
});
|
||
|
||
server.listen(PORT, () => {
|
||
console.log(`Сервер заявок запущен на порту ${PORT}`);
|
||
});
|