한글뷰어 기능수정 Ver.01

This commit is contained in:
koj729
2026-06-19 17:58:47 +09:00
parent 9268e4e6bc
commit 83b6e891ab
49 changed files with 8741 additions and 446 deletions

View File

@@ -615,34 +615,63 @@ exports.deleteUser = async (req, res) => {
// 5. 활동 로그 조회 (Activity Logs)
exports.getAuditLogs = async (req, res) => {
const { user_id, activity, project_nm } = req.query;
let { user_id, activity, project_nm, page = 1, limit = 20 } = req.query;
page = parseInt(page);
limit = parseInt(limit);
const offset = (page - 1) * limit;
const client = await pool.connect();
try {
let countQuery = `
SELECT COUNT(*) as total
FROM ver4.${tbLog} l
LEFT JOIN ver4.${tbProject} p ON l.project_id = p.project_id
WHERE 1=1
`;
let query = `
SELECT l.log_id, l.log_date as clean_date, l.project_id, p.project_nm, l.user_id, l.user_ip, l.activity as clean_path, l.path_arr as criteria_info
FROM ver4.${tbLog} l
LEFT JOIN ver4.${tbProject} p ON l.project_id = p.project_id
WHERE 1=1
`;
const params = [];
const filterParams = [];
let paramIndex = 1;
let filterSql = '';
if (user_id) {
query += ` AND l.user_id ILIKE $${paramIndex++}`;
params.push(`%${user_id}%`);
filterSql += ` AND l.user_id ILIKE $${paramIndex++}`;
filterParams.push(`%${user_id}%`);
}
if (project_nm) {
query += ` AND (p.project_nm ILIKE $${paramIndex++} OR l.project_id ILIKE $${paramIndex - 1})`;
params.push(`%${project_nm}%`);
filterSql += ` AND (p.project_nm ILIKE $${paramIndex++} OR l.project_id ILIKE $${paramIndex - 1})`;
filterParams.push(`%${project_nm}%`);
}
if (activity && activity !== 'all') {
query += ` AND l.activity ILIKE $${paramIndex++}`;
params.push(`%${activity}%`);
filterSql += ` AND l.activity ILIKE $${paramIndex++}`;
filterParams.push(`%${activity}%`);
}
query += ` ORDER BY l.log_id DESC LIMIT 100;`;
const result = await client.query(query, params);
res.status(200).json(result.rows);
countQuery += filterSql;
query += filterSql;
const countResult = await client.query(countQuery, filterParams);
const total = parseInt(countResult.rows[0].total);
query += ` ORDER BY l.log_id DESC LIMIT $${paramIndex++} OFFSET $${paramIndex++};`;
const dataParams = [...filterParams, limit, offset];
const result = await client.query(query, dataParams);
res.status(200).json({
data: result.rows,
pagination: {
total,
page,
limit,
totalPages: Math.ceil(total / limit)
}
});
} catch (err) {
console.error("getAuditLogs Error:", err);
res.status(500).json({ error: "활동 로그 조회 실패" });

View File

@@ -795,148 +795,15 @@ async function insertData(params) {
}
async function insertLog(params, from) {
let { projectId, activity, userInfoString, userIp, resourcePathArr, dataIdArr, isExpiredFolder } = params;
if (from) {
console.log();
console.log(`=======================================`);
console.log(`${from}에서 insertLog 실행 (${makePostgresTimestamp()})`);
console.log(userInfoString);
console.log('isExpiredFolder: ', isExpiredFolder);
console.log(`=======================================`);
console.log();
}
if (activity == 'removeTarget_folder' && isExpiredFolder) activity = `${activity}_expired`
let userInfo = JSON.parse(userInfoString);
let userId = userInfo.user_id;
let dateNow = makePostgresTimestamp(Date.now());
const client = await pool.connect();
try {
let parsedResourcePathArr = resourcePathArr;
if (typeof resourcePathArr === 'string') {
try {
parsedResourcePathArr = JSON.parse(resourcePathArr);
} catch(e) {}
}
if (!Array.isArray(parsedResourcePathArr)) {
parsedResourcePathArr = [parsedResourcePathArr];
}
let parsedDataIdArr = dataIdArr;
if (typeof dataIdArr === 'string') {
try {
parsedDataIdArr = JSON.parse(dataIdArr);
} catch(e) {}
}
if (!Array.isArray(parsedDataIdArr)) {
parsedDataIdArr = [parsedDataIdArr];
}
let values = [
projectId,
activity,
userId,
userIp,
dateNow,
parsedResourcePathArr,
parsedDataIdArr
];
let queryString = `
INSERT INTO ver4.${tbLog} (
project_id, activity, user_id, user_ip, log_date, path_arr, data_id_arr
)
VALUES (
$1, $2, $3, $4, $5, $6, $7
);
`;
// console.log('=================');
// console.log(queryString);
await client.query(queryString, values);
let result = { message: 'insertLog_success' };
return result;
} catch(error) {
console.error("insertLog err:", error);
return { message: 'insertLog_failed', error: error };
} finally {
client.release();
}
// console.log('============================');
// console.log(projectId);
// console.log(activity);
// console.log(userId);
// console.log(userIp);
// console.log(resourcePathArr);
// console.log(dataIdArr);
// Synchronous database inserts for activity log are now handled asynchronously
// by the activityLogger middleware via BullMQ.
return { message: 'insertLog_success' };
}
async function insertClickLog(params) {
let { projectId, activity, userInfoString, userIp, resourcePathArr, dataIdArr } = params;
let userInfo = JSON.parse(userInfoString);
let userId = userInfo.user_id;
let dateNow = makePostgresTimestamp(Date.now());
const client = await pool.connect();
try {
let parsedResourcePathArr = resourcePathArr;
if (typeof resourcePathArr === 'string') {
try {
parsedResourcePathArr = JSON.parse(resourcePathArr);
} catch(e) {}
}
if (!Array.isArray(parsedResourcePathArr)) {
parsedResourcePathArr = [parsedResourcePathArr];
}
let parsedDataIdArr = dataIdArr;
if (typeof dataIdArr === 'string') {
try {
parsedDataIdArr = JSON.parse(dataIdArr);
} catch(e) {}
}
if (!Array.isArray(parsedDataIdArr)) {
parsedDataIdArr = [parsedDataIdArr];
}
let values = [
projectId,
activity,
userId,
userIp,
dateNow,
parsedResourcePathArr,
parsedDataIdArr
];
let queryString = `
INSERT INTO ver4.${tbClickLog} (
project_id, activity, user_id, user_ip, log_date, path_arr, data_id_arr
)
VALUES (
$1, $2, $3, $4, $5, $6, $7
);
`;
// console.log('=================');
// console.log(queryString);
await client.query(queryString, values);
let result = { message: 'insertClickLog_success' };
return result;
} catch(error) {
console.error("insertClickLog err:", error);
} finally {
client.release();
}
// Synchronous database inserts for click log are now handled asynchronously
// by the activityLogger middleware via BullMQ.
return { message: 'insertClickLog_success' };
}
/*

View File

@@ -13,6 +13,7 @@ const convertQueue3 = new Queue('zip-folder', { connection: redisConnection });
const convertQueue4 = new Queue('post-process-video', { connection: redisConnection });
const convertQueue5 = new Queue('ai-summarize', { connection: redisConnection });
const convertQueue6 = new Queue('api-summarize', {connection: redisConnection});
const convertQueue7 = new Queue('activity-log', {connection: redisConnection});
// const convertQueue3 = new Queue('test-job', { connection: redisConnection });
// 2) ExpressAdapter 생성 및 기본 경로 설정
@@ -28,6 +29,7 @@ createBullBoard({
new BullMQAdapter(convertQueue4),
new BullMQAdapter(convertQueue5),
new BullMQAdapter(convertQueue6),
new BullMQAdapter(convertQueue7),
// new BullMQAdapter(convertQueue3),
// 여기에 더 필요한 큐 어댑터를 추가할 수 있습니다.
],

View File

@@ -43,7 +43,14 @@ exports.getProject = async (req,res,next)=>{
try {
// 테스트
let queryString = `
select p.*, u.*
select p.*, u.*,
(SELECT notice_text
FROM ver4.tb_banner_notice b
WHERE (b.project_id = p.project_id OR b.project_id IS NULL)
AND b.status_code = 'NOTICE_STATUS_active'
AND CURRENT_DATE BETWEEN b.start_date AND b.end_date
ORDER BY b.banner_id DESC
LIMIT 1) as banner_notice
from ver4.${tbProject} p
inner join ver4.tb_user u
on p.user_id = u.user_id