ваше сообщение коммита

This commit is contained in:
2025-07-16 17:25:58 +03:00
parent d952e89a26
commit 32acc60360
27 changed files with 539 additions and 138 deletions

View File

@@ -9,6 +9,7 @@ const crypto = require('crypto');
const aiAssistantSettingsService = require('../services/aiAssistantSettingsService');
const aiAssistantRulesService = require('../services/aiAssistantRulesService');
const { isUserBlocked } = require('../utils/userUtils');
const { broadcastChatMessage } = require('../wsHub');
// Настройка multer для обработки файлов в памяти
const storage = multer.memoryStorage();
@@ -460,7 +461,7 @@ router.post('/message', requireAuth, upload.array('attachments'), async (req, re
logger.info(`[RAG] Запуск поиска по RAG: tableId=${ragTableId}, вопрос="${messageContent}", threshold=${threshold}`);
const ragResult = await ragAnswer({ tableId: ragTableId, userQuestion: messageContent, threshold });
logger.info(`[RAG] Результат поиска по RAG:`, ragResult);
if (ragResult && ragResult.answer && ragResult.score && ragResult.score > threshold) {
if (ragResult && ragResult.answer && typeof ragResult.score === 'number' && Math.abs(ragResult.score) <= threshold) {
logger.info(`[RAG] Найден confident-ответ (score=${ragResult.score}), отправляем ответ из базы.`);
// Прямой ответ из RAG
const aiMessageResult = await db.getQuery()(
@@ -471,6 +472,8 @@ router.post('/message', requireAuth, upload.array('attachments'), async (req, re
[conversationId, userId, ragResult.answer]
);
aiMessage = aiMessageResult.rows[0];
// Пушим новое сообщение через WebSocket
broadcastChatMessage(aiMessage);
} else if (ragResult) {
logger.info(`[RAG] Нет confident-ответа (score=${ragResult.score}), переходим к генерации через LLM.`);
// Генерация через LLM с подстановкой значений из RAG
@@ -502,6 +505,8 @@ router.post('/message', requireAuth, upload.array('attachments'), async (req, re
[conversationId, userId, llmResponse]
);
aiMessage = aiMessageResult.rows[0];
// Пушим новое сообщение через WebSocket
broadcastChatMessage(aiMessage);
} else {
logger.info(`[RAG] Нет ни одного результата, прошедшего порог (${threshold}).`);
}

136
backend/routes/pages.js Normal file
View File

@@ -0,0 +1,136 @@
const express = require('express');
const router = express.Router();
const db = require('../db');
const FIELDS_TO_EXCLUDE = ['image', 'tags'];
// Проверка и создание таблицы для пользователя-админа
async function ensureUserPagesTable(userId, fields) {
fields = fields.filter(f => !FIELDS_TO_EXCLUDE.includes(f));
const tableName = `pages_user_${userId}`;
// Проверяем, есть ли таблица
const existsRes = await db.getQuery()(
`SELECT to_regclass($1) as exists`, [tableName]
);
if (!existsRes.rows[0].exists) {
// Формируем SQL для создания таблицы с нужными полями
let columns = [
'id SERIAL PRIMARY KEY',
'created_at TIMESTAMP DEFAULT NOW()',
'updated_at TIMESTAMP DEFAULT NOW()'
];
for (const field of fields) {
columns.push(`"${field}" TEXT`);
}
const sql = `CREATE TABLE ${tableName} (${columns.join(', ')})`;
await db.getQuery()(sql);
} else {
// Проверяем, есть ли все нужные столбцы, и добавляем недостающие
const colRes = await db.getQuery()(
`SELECT column_name FROM information_schema.columns WHERE table_name = $1`, [tableName]
);
const existingCols = colRes.rows.map(r => r.column_name);
for (const field of fields) {
if (!existingCols.includes(field)) {
await db.getQuery()(
`ALTER TABLE ${tableName} ADD COLUMN "${field}" TEXT`
);
}
}
}
return tableName;
}
// Создать страницу (только для админа)
router.post('/', async (req, res) => {
if (!req.user || !req.user.isAdmin) {
return res.status(403).json({ error: 'Only admin can create pages' });
}
const userId = req.user.id;
const fields = Object.keys(req.body).filter(f => !FIELDS_TO_EXCLUDE.includes(f));
const filteredBody = {};
fields.forEach(f => { filteredBody[f] = req.body[f]; });
const tableName = await ensureUserPagesTable(userId, fields);
// Формируем SQL для вставки данных
const colNames = fields.map(f => `"${f}"`).join(', ');
const values = Object.values(filteredBody);
const placeholders = values.map((_, i) => `$${i + 1}`).join(', ');
const sql = `INSERT INTO ${tableName} (${colNames}) VALUES (${placeholders}) RETURNING *`;
const { rows } = await db.getQuery()(sql, values);
res.json(rows[0]);
});
// Получить все страницы пользователя-админа
router.get('/', async (req, res) => {
if (!req.user || !req.user.isAdmin) {
return res.status(403).json({ error: 'Only admin can view pages' });
}
const userId = req.user.id;
const tableName = `pages_user_${userId}`;
// Проверяем, есть ли таблица
const existsRes = await db.getQuery()(
`SELECT to_regclass($1) as exists`, [tableName]
);
if (!existsRes.rows[0].exists) return res.json([]);
const { rows } = await db.getQuery()(`SELECT * FROM ${tableName} ORDER BY created_at DESC`);
res.json(rows);
});
// Получить одну страницу по id
router.get('/:id', async (req, res) => {
if (!req.user || !req.user.isAdmin) {
return res.status(403).json({ error: 'Only admin can view pages' });
}
const userId = req.user.id;
const tableName = `pages_user_${userId}`;
const existsRes = await db.getQuery()(
`SELECT to_regclass($1) as exists`, [tableName]
);
if (!existsRes.rows[0].exists) return res.status(404).json({ error: 'Page table not found' });
const { rows } = await db.getQuery()(`SELECT * FROM ${tableName} WHERE id = $1`, [req.params.id]);
if (!rows.length) return res.status(404).json({ error: 'Page not found' });
res.json(rows[0]);
});
// Редактировать страницу по id
router.patch('/:id', async (req, res) => {
if (!req.user || !req.user.isAdmin) {
return res.status(403).json({ error: 'Only admin can edit pages' });
}
const userId = req.user.id;
const tableName = `pages_user_${userId}`;
const existsRes = await db.getQuery()(
`SELECT to_regclass($1) as exists`, [tableName]
);
if (!existsRes.rows[0].exists) return res.status(404).json({ error: 'Page table not found' });
const fields = Object.keys(req.body).filter(f => !FIELDS_TO_EXCLUDE.includes(f));
if (!fields.length) return res.status(400).json({ error: 'No fields to update' });
const filteredBody = {};
fields.forEach(f => { filteredBody[f] = req.body[f]; });
const setClause = fields.map((f, i) => `"${f}" = $${i + 1}`).join(', ');
const values = Object.values(filteredBody);
values.push(req.params.id);
const sql = `UPDATE ${tableName} SET ${setClause}, updated_at = NOW() WHERE id = $${fields.length + 1} RETURNING *`;
const { rows } = await db.getQuery()(sql, values);
if (!rows.length) return res.status(404).json({ error: 'Page not found' });
res.json(rows[0]);
});
// Удалить страницу по id
router.delete('/:id', async (req, res) => {
if (!req.user || !req.user.isAdmin) {
return res.status(403).json({ error: 'Only admin can delete pages' });
}
const userId = req.user.id;
const tableName = `pages_user_${userId}`;
const existsRes = await db.getQuery()(
`SELECT to_regclass($1) as exists`, [tableName]
);
if (!existsRes.rows[0].exists) return res.status(404).json({ error: 'Page table not found' });
const { rows } = await db.getQuery()(`DELETE FROM ${tableName} WHERE id = $1 RETURNING *`, [req.params.id]);
if (!rows.length) return res.status(404).json({ error: 'Page not found' });
res.json(rows[0]);
});
module.exports = router;