admin_to_react
This commit is contained in:
@@ -0,0 +1,7 @@
|
||||
# Документы
|
||||
|
||||
Поместите ваш файл справочника с именем `handbook.docx` в эту папку.
|
||||
|
||||
Структура:
|
||||
- `handbook.docx` - основной справочник
|
||||
- Другие документы можно добавить по необходимости
|
||||
@@ -0,0 +1,2 @@
|
||||
COM_PORT=COM6
|
||||
COM_SPEED=9600
|
||||
@@ -0,0 +1,201 @@
|
||||
const { app, BrowserWindow, protocol, ipcMain, globalShortcut } = require('electron');
|
||||
const path = require('path');
|
||||
require('dotenv').config({path: path.join(__dirname, 'config.env')})
|
||||
const isDev = require('electron-is-dev');
|
||||
const fs = require('fs');
|
||||
const COM_PORT = process.env.COM_PORT;
|
||||
const COM_SPEED = process.env.COM_SPEED;
|
||||
const { SerialPort } = require('serialport');
|
||||
const axios = require('axios');
|
||||
const { logger } = require('../../backend/src/config/logger');
|
||||
const config = require('../src/config.json')
|
||||
protocol.registerSchemesAsPrivileged([
|
||||
{
|
||||
scheme: 'app',
|
||||
privileges: {
|
||||
secure: true,
|
||||
standard: true,
|
||||
supportFetchAPI: true,
|
||||
corsEnabled: true
|
||||
}
|
||||
}
|
||||
]);
|
||||
|
||||
if (!Promise.withResolvers) {
|
||||
Promise.withResolvers = function () {
|
||||
let resolve, reject;
|
||||
const promise = new Promise((res, rej) => {
|
||||
resolve = res;
|
||||
reject = rej;
|
||||
});
|
||||
return { promise, resolve, reject };
|
||||
};
|
||||
}
|
||||
|
||||
let mainWindow;
|
||||
let appConfig = {};
|
||||
const configPath = isDev
|
||||
? path.join(__dirname, '../src/config.json')
|
||||
: path.join(process.resourcesPath, 'config.json');
|
||||
|
||||
try {
|
||||
logger.info(`[Config] Trying to load config from: ${configPath}`);
|
||||
if (fs.existsSync(configPath)) {
|
||||
appConfig = JSON.parse(fs.readFileSync(configPath, 'utf-8'));
|
||||
logger.info('[Config] External config loaded successfully:', appConfig);
|
||||
} else {
|
||||
logger.warn('[Config] External config file not found. Using default values.');
|
||||
}
|
||||
} catch (error) {
|
||||
logger.error('[Config] Could not load external config file:', error);
|
||||
}
|
||||
|
||||
global.allowClose = false;
|
||||
|
||||
function createWindow() {
|
||||
const preloadPath = path.join(__dirname, 'preload.js');
|
||||
try {
|
||||
fs.accessSync(preloadPath);
|
||||
logger.debug(`[DEBUG] Preload script found at: ${preloadPath}`);
|
||||
} catch (e) {
|
||||
logger.error(`[FATAL] Preload script not found at: ${preloadPath}`);
|
||||
app.quit();
|
||||
return;
|
||||
}
|
||||
|
||||
mainWindow = new BrowserWindow({
|
||||
kiosk: true,
|
||||
titleBarStyle:'hidden',
|
||||
alwaysOnTop: false,
|
||||
webPreferences: {
|
||||
preload: preloadPath,
|
||||
contextIsolation: true,
|
||||
nodeIntegration: false
|
||||
|
||||
},
|
||||
});
|
||||
|
||||
mainWindow.loadURL(
|
||||
isDev
|
||||
? `${config.frontUrl}`
|
||||
: `file://${path.join(__dirname, '../build/index.html')}`
|
||||
);
|
||||
|
||||
mainWindow.on('close', (e) => {
|
||||
if (!global.allowClose) {
|
||||
e.preventDefault();
|
||||
}
|
||||
});
|
||||
|
||||
mainWindow.on('minimize', (e) => {
|
||||
e.preventDefault();
|
||||
});
|
||||
}
|
||||
|
||||
app.whenReady().then(() => {
|
||||
createWindow();
|
||||
global.allowMinimize = false;
|
||||
globalShortcut.register('Control+Alt+Backspace', () => {
|
||||
global.allowMinimize = true;
|
||||
if (mainWindow) mainWindow.minimize();
|
||||
});
|
||||
|
||||
mainWindow.on('minimize', function (event) {
|
||||
if (global.allowMinimize) {
|
||||
global.allowMinimize = false;
|
||||
return;
|
||||
}
|
||||
event.preventDefault();
|
||||
setTimeout(() => {
|
||||
if (mainWindow.isMinimized()) {
|
||||
mainWindow.restore();
|
||||
mainWindow.focus();
|
||||
}
|
||||
}, 10);
|
||||
});
|
||||
globalShortcut.register('Control+Alt+Enter', () => {
|
||||
global.allowClose = true;
|
||||
app.quit();
|
||||
});
|
||||
|
||||
globalShortcut.register('F11', () => {
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
app.on('window-all-closed', () => {
|
||||
if (process.platform !== 'darwin') {
|
||||
app.quit();
|
||||
}
|
||||
});
|
||||
|
||||
app.on('activate', () => {
|
||||
if (mainWindow === null) {
|
||||
createWindow();
|
||||
}
|
||||
});
|
||||
|
||||
app.on('will-quit', () => {
|
||||
globalShortcut.unregisterAll();
|
||||
});
|
||||
|
||||
//считыватель
|
||||
SerialPort.list().then(ports => {
|
||||
logger.info('Доступные порты:', ports.map(p => p.path));
|
||||
}).catch(err => {
|
||||
logger.error('Ошибка при получении списка портов:', err);
|
||||
});
|
||||
try {
|
||||
const port = new SerialPort({ path: COM_PORT, baudRate: parseInt(COM_SPEED, 10)});
|
||||
let buffer = '';
|
||||
port.on('open', () => {
|
||||
logger.info(' Serial port открыт');
|
||||
});
|
||||
port.on('data', (data) => {
|
||||
logger.info('RAW DATA:', data);
|
||||
buffer += data.toString('utf8');
|
||||
if (buffer.includes('\n')) {
|
||||
const lines = buffer.split('\n');
|
||||
lines.forEach((line, idx) => {
|
||||
if (idx < lines.length - 1) {
|
||||
const uid = line.trim().replace(/\D/g, '');
|
||||
if (uid) {
|
||||
console.log(`UID карты: ${uid}`);
|
||||
console.log('[DEBUG] Отправляю событие на admin-server:', {
|
||||
event: 'CARD_PLACED',
|
||||
uid: uid,
|
||||
timestamp: Date.now()
|
||||
});
|
||||
axios.post(`${config.adminUrl}}/api/card-event`, {
|
||||
event: 'CARD_PLACED',
|
||||
uid: uid,
|
||||
timestamp: Date.now()
|
||||
}).catch(err => {
|
||||
console.error('[ADMIN][CARD_LOG] Ошибка отправки:', err.message);
|
||||
});
|
||||
if (mainWindow && mainWindow.webContents) {
|
||||
mainWindow.webContents.send('card-detected', uid);
|
||||
console.log(` Отправка события 'card-detected' в рендерер с UID: ${uid}`);
|
||||
} else {
|
||||
console.warn('mainWindow или webContents не определены, событие не отправлено');
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
buffer = lines[lines.length - 1];
|
||||
}
|
||||
});
|
||||
port.on('error', (err) => {
|
||||
console.error('Ошибка serialport:', err);
|
||||
});
|
||||
} catch (err) {
|
||||
console.error('!!! FATAL: FAILED TO INITIALIZE SERIALPORT !!!', err);
|
||||
}
|
||||
|
||||
ipcMain.handle('get-app-config', async (event) => {
|
||||
console.log('[IPC] Renderer requested app config. Sending:', appConfig);
|
||||
return appConfig;
|
||||
});
|
||||
|
||||
app.whenReady().then(() => {
|
||||
});
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 3.8 KiB |
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,49 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
|
||||
<link href="https://cdn.quilljs.com/1.3.6/quill.snow.css" rel="stylesheet">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<meta name="theme-color" content="#000000" />
|
||||
<meta
|
||||
name="description"
|
||||
content="Web site created using create-react-app"
|
||||
/>
|
||||
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
|
||||
<!--
|
||||
manifest.json provides metadata used when your web app is installed on a
|
||||
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
|
||||
-->
|
||||
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
|
||||
<!--
|
||||
Notice the use of %PUBLIC_URL% in the tags above.
|
||||
It will be replaced with the URL of the `public` folder during the build.
|
||||
Only files inside the `public` folder can be referenced from the HTML.
|
||||
|
||||
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
|
||||
work correctly both with client-side routing and a non-root public URL.
|
||||
Learn how to configure a non-root public URL by running `npm run build`.
|
||||
-->
|
||||
<title>Инфокиоск</title>
|
||||
</head>
|
||||
<body>
|
||||
<noscript>You need to enable JavaScript to run this app.</noscript>
|
||||
<div id="root"></div>
|
||||
<style>
|
||||
.ql-align-center { text-align: center; }
|
||||
.ql-align-right { text-align: right; }
|
||||
.ql-align-justify { text-align: justify; }
|
||||
</style>
|
||||
<!--
|
||||
This HTML file is a template.
|
||||
If you open it directly in the browser, you will see an empty page.
|
||||
|
||||
You can add webfonts, meta tags, or analytics to this file.
|
||||
The build step will place the bundled scripts into the <body> tag.
|
||||
|
||||
To begin the development, run `npm start` or `yarn start`.
|
||||
To create a production bundle, use `npm run build` or `yarn build`.
|
||||
-->
|
||||
</body>
|
||||
</html>
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 5.2 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 9.4 KiB |
@@ -0,0 +1,25 @@
|
||||
{
|
||||
"short_name": "React App",
|
||||
"name": "Create React App Sample",
|
||||
"icons": [
|
||||
{
|
||||
"src": "favicon.ico",
|
||||
"sizes": "64x64 32x32 24x24 16x16",
|
||||
"type": "image/x-icon"
|
||||
},
|
||||
{
|
||||
"src": "logo192.png",
|
||||
"type": "image/png",
|
||||
"sizes": "192x192"
|
||||
},
|
||||
{
|
||||
"src": "logo512.png",
|
||||
"type": "image/png",
|
||||
"sizes": "512x512"
|
||||
}
|
||||
],
|
||||
"start_url": ".",
|
||||
"display": "standalone",
|
||||
"theme_color": "#000000",
|
||||
"background_color": "#ffffff"
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
Vendored
+75390
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,19 @@
|
||||
const { logger } = require('../../backend/src/config/logger');
|
||||
logger.info('[Preload] Script started.');
|
||||
const { contextBridge, ipcRenderer } = require('electron');
|
||||
contextBridge.exposeInMainWorld(
|
||||
'electronAPI',
|
||||
{
|
||||
getAppConfig: () => ipcRenderer.invoke('get-app-config'),
|
||||
onCardDetected: (callback) => {
|
||||
ipcRenderer.on('card-detected', (event, uid) => callback(uid));
|
||||
},
|
||||
|
||||
removeCardDetectedListeners: () => {
|
||||
ipcRenderer.removeAllListeners('card-detected');
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
logger.log('[Preload] Script finished. electronAPI exposed.');
|
||||
window.dispatchEvent(new Event('electronApiReady'));
|
||||
@@ -0,0 +1,4 @@
|
||||
# https://www.robotstxt.org/robotstxt.html
|
||||
User-agent: *
|
||||
Disallow:
|
||||
|
||||
Reference in New Issue
Block a user