2
This commit is contained in:
parent
15280bacc6
commit
c584dcac4e
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,3 +1,4 @@
|
|||||||
node_modules/
|
node_modules/
|
||||||
*/node_modules/
|
*/node_modules/
|
||||||
*/build/
|
*/build/
|
||||||
|
.env
|
||||||
|
|||||||
110
api.php
Normal file
110
api.php
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
<?php
|
||||||
|
// api.php
|
||||||
|
|
||||||
|
header('Content-Type: application/json');
|
||||||
|
|
||||||
|
// --- Helper function to get environment variables ---
|
||||||
|
function get_env($key, $default = null) {
|
||||||
|
$path = __DIR__ . '/.env';
|
||||||
|
if (!file_exists($path)) {
|
||||||
|
return $default;
|
||||||
|
}
|
||||||
|
$lines = file($path, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
|
||||||
|
foreach ($lines as $line) {
|
||||||
|
if (strpos(trim($line), '#') === 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
list($name, $value) = explode('=', $line, 2);
|
||||||
|
$name = trim($name);
|
||||||
|
$value = trim($value);
|
||||||
|
if ($name === $key) {
|
||||||
|
return $value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $default;
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- Main Logic ---
|
||||||
|
|
||||||
|
// 1. Get API Key
|
||||||
|
$apiKey = get_env('GEMINI_API_KEY');
|
||||||
|
if (!$apiKey) {
|
||||||
|
echo json_encode(['reply' => 'Ошибка: API-ключ не найден. Пожалуйста, добавьте его в файл .env']);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. Get user message from POST request
|
||||||
|
$input = json_decode(file_get_contents('php://input'), true);
|
||||||
|
$userMessage = trim($input['message'] ?? '');
|
||||||
|
|
||||||
|
if (empty($userMessage)) {
|
||||||
|
echo json_encode(['reply' => 'Пожалуйста, введите сообщение.']);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. Load the knowledge base
|
||||||
|
$knowledgeBasePath = __DIR__ . '/db/knowledge_base.txt';
|
||||||
|
if (!file_exists($knowledgeBasePath)) {
|
||||||
|
echo json_encode(['reply' => 'Ошибка: База знаний не найдена.']);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
$knowledgeBase = file_get_contents($knowledgeBasePath);
|
||||||
|
|
||||||
|
// 4. Prepare the prompt for the AI
|
||||||
|
$prompt = "Ты — ИИ-ассистент, специалист по внутренней системе управления складом под названием HUB. Твоя задача — отвечать на вопросы пользователя, основываясь ИСКЛЮЧИТЕЛЬНО на предоставленной базе знаний. Не придумывай ничего от себя. Если ответа в базе знаний нет, вежливо сообщи, что ты можешь отвечать только на вопросы, связанные с системой HUB.\n\nВот база знаний:\n---\n" . $knowledgeBase . "\n---\n\nВопрос пользователя: \"" . $userMessage . "\"";
|
||||||
|
|
||||||
|
// 5. Call the Gemini API
|
||||||
|
$url = 'https://generativelanguage.googleapis.com/v1beta/models/gemini-pro:generateContent?key=' . $apiKey;
|
||||||
|
|
||||||
|
$data = [
|
||||||
|
'contents' => [
|
||||||
|
[
|
||||||
|
'parts' => [
|
||||||
|
['text' => $prompt]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
];
|
||||||
|
|
||||||
|
$options = [
|
||||||
|
'http' => [
|
||||||
|
'header' => "Content-type: application/json\r\n",
|
||||||
|
'method' => 'POST',
|
||||||
|
'content' => json_encode($data),
|
||||||
|
'ignore_errors' => true // To see the error message from the API
|
||||||
|
]
|
||||||
|
];
|
||||||
|
|
||||||
|
$context = stream_context_create($options);
|
||||||
|
$response = file_get_contents($url, false, $context);
|
||||||
|
$http_response_header = $http_response_header ?? [];
|
||||||
|
|
||||||
|
// 6. Process the response
|
||||||
|
if ($response === FALSE) {
|
||||||
|
$error = 'Не удалось связаться с API. ';
|
||||||
|
// Check for more specific errors if possible
|
||||||
|
$last_error = error_get_last();
|
||||||
|
if ($last_error) {
|
||||||
|
$error .= $last_error['message'];
|
||||||
|
}
|
||||||
|
// Try to get the HTTP status and response body
|
||||||
|
$status_line = $http_response_header[0] ?? 'HTTP/1.1 500 Internal Server Error';
|
||||||
|
preg_match('{HTTP/\S+\s(\d+)}', $status_line, $match);
|
||||||
|
$status = $match[1] ?? 500;
|
||||||
|
|
||||||
|
error_log("Gemini API Error: Status $status, Response: $response");
|
||||||
|
|
||||||
|
echo json_encode(['reply' => "Ошибка при обращении к сервису ИИ. Статус: $status. Пожалуйста, проверьте ключ API и настройки сервера."]);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
$result = json_decode($response, true);
|
||||||
|
|
||||||
|
if (isset($result['candidates'][0]['content']['parts'][0]['text'])) {
|
||||||
|
$reply = $result['candidates'][0]['content']['parts'][0]['text'];
|
||||||
|
echo json_encode(['reply' => $reply]);
|
||||||
|
} else {
|
||||||
|
// Log the actual error response from the API for debugging
|
||||||
|
error_log("Gemini API - Unexpected response structure: " . $response);
|
||||||
|
echo json_encode(['reply' => 'Получен неожиданный ответ от сервиса ИИ. Возможно, проблема с конфигурацией или ключом API.']);
|
||||||
|
}
|
||||||
|
}
|
||||||
163
assets/css/custom.css
Normal file
163
assets/css/custom.css
Normal file
@ -0,0 +1,163 @@
|
|||||||
|
|
||||||
|
:root {
|
||||||
|
--bg-color: #121212;
|
||||||
|
--surface-color: #1E1E1E;
|
||||||
|
--primary-color: #00FF9B;
|
||||||
|
--secondary-color: #00C2FF;
|
||||||
|
--text-color: #E0E0E0;
|
||||||
|
--text-muted-color: #888;
|
||||||
|
--border-radius-md: 12px;
|
||||||
|
--border-radius-sm: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
background-color: var(--bg-color);
|
||||||
|
color: var(--text-color);
|
||||||
|
font-family: 'Roboto Mono', 'Consolas', 'Monaco', monospace;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
height: 100vh;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chat-container {
|
||||||
|
width: 100%;
|
||||||
|
max-width: 800px;
|
||||||
|
height: 100vh;
|
||||||
|
max-height: 100vh; /* For mobile browsers */
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
background-color: var(--bg-color);
|
||||||
|
border-radius: 0;
|
||||||
|
box-shadow: 0 0 40px rgba(0, 255, 155, 0.1);
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chat-header {
|
||||||
|
padding: 16px 24px;
|
||||||
|
background-color: var(--surface-color);
|
||||||
|
border-bottom: 1px solid #333;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chat-header h1 {
|
||||||
|
font-size: 1.5rem;
|
||||||
|
font-weight: 500;
|
||||||
|
margin: 0;
|
||||||
|
background: linear-gradient(90deg, var(--primary-color), var(--secondary-color));
|
||||||
|
-webkit-background-clip: text;
|
||||||
|
-webkit-text-fill-color: transparent;
|
||||||
|
background-clip: text;
|
||||||
|
text-fill-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chat-header .text-muted {
|
||||||
|
font-size: 0.85rem;
|
||||||
|
color: var(--text-muted-color);
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chat-messages {
|
||||||
|
flex-grow: 1;
|
||||||
|
padding: 24px;
|
||||||
|
overflow-y: auto;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Custom scrollbar for webkit browsers */
|
||||||
|
.chat-messages::-webkit-scrollbar {
|
||||||
|
width: 6px;
|
||||||
|
}
|
||||||
|
.chat-messages::-webkit-scrollbar-track {
|
||||||
|
background: var(--bg-color);
|
||||||
|
}
|
||||||
|
.chat-messages::-webkit-scrollbar-thumb {
|
||||||
|
background-color: var(--surface-color);
|
||||||
|
border-radius: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.message {
|
||||||
|
display: flex;
|
||||||
|
max-width: 75%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.message-content {
|
||||||
|
padding: 12px 16px;
|
||||||
|
border-radius: var(--border-radius-md);
|
||||||
|
line-height: 1.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.message-content p {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bot-message {
|
||||||
|
align-self: flex-start;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bot-message .message-content {
|
||||||
|
background-color: var(--surface-color);
|
||||||
|
border-top-left-radius: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-message {
|
||||||
|
align-self: flex-end;
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-message .message-content {
|
||||||
|
background: linear-gradient(135deg, var(--primary-color), var(--secondary-color));
|
||||||
|
color: #000;
|
||||||
|
border-top-right-radius: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chat-input-area {
|
||||||
|
padding: 16px 24px;
|
||||||
|
background-color: var(--surface-color);
|
||||||
|
border-top: 1px solid #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
#chat-form .form-control {
|
||||||
|
background-color: #333;
|
||||||
|
border: 1px solid #444;
|
||||||
|
color: var(--text-color);
|
||||||
|
border-radius: var(--border-radius-sm);
|
||||||
|
padding: 12px 16px;
|
||||||
|
height: 48px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#chat-form .form-control:focus {
|
||||||
|
background-color: #333;
|
||||||
|
color: var(--text-color);
|
||||||
|
box-shadow: 0 0 0 2px var(--primary-color);
|
||||||
|
border-color: var(--primary-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
#chat-form .form-control::placeholder {
|
||||||
|
color: var(--text-muted-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
#chat-form .btn {
|
||||||
|
background: linear-gradient(135deg, var(--primary-color), var(--secondary-color));
|
||||||
|
border: none;
|
||||||
|
border-radius: var(--border-radius-sm);
|
||||||
|
margin-left: 12px;
|
||||||
|
width: 48px;
|
||||||
|
height: 48px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
transition: transform 0.2s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
#chat-form .btn:hover {
|
||||||
|
transform: scale(1.05);
|
||||||
|
}
|
||||||
|
|
||||||
|
#chat-form .btn svg {
|
||||||
|
color: #000;
|
||||||
|
}
|
||||||
84
assets/js/main.js
Normal file
84
assets/js/main.js
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
document.addEventListener('DOMContentLoaded', () => {
|
||||||
|
const chatForm = document.getElementById('chat-form');
|
||||||
|
const messageInput = document.getElementById('message-input');
|
||||||
|
const chatMessages = document.getElementById('chat-messages');
|
||||||
|
|
||||||
|
chatForm.addEventListener('submit', (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
const messageText = messageInput.value.trim();
|
||||||
|
|
||||||
|
if (messageText) {
|
||||||
|
appendMessage(messageText, 'user');
|
||||||
|
messageInput.value = '';
|
||||||
|
|
||||||
|
showBotTyping();
|
||||||
|
|
||||||
|
// Send message to backend
|
||||||
|
fetch('api.php', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
},
|
||||||
|
body: JSON.stringify({ message: messageText })
|
||||||
|
})
|
||||||
|
.then(response => response.json())
|
||||||
|
.then(data => {
|
||||||
|
removeBotTyping();
|
||||||
|
appendMessage(data.reply, 'bot');
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
removeBotTyping();
|
||||||
|
console.error('Error:', error);
|
||||||
|
appendMessage('Извините, произошла ошибка. Попробуйте еще раз.', 'bot');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
function appendMessage(text, sender) {
|
||||||
|
const messageWrapper = document.createElement('div');
|
||||||
|
messageWrapper.classList.add('message', `${sender}-message`);
|
||||||
|
|
||||||
|
const messageContent = document.createElement('div');
|
||||||
|
messageContent.classList.add('message-content');
|
||||||
|
|
||||||
|
const paragraph = document.createElement('p');
|
||||||
|
paragraph.innerHTML = text; // Use innerHTML to render potential HTML tags from response
|
||||||
|
|
||||||
|
messageContent.appendChild(paragraph);
|
||||||
|
messageWrapper.appendChild(messageContent);
|
||||||
|
chatMessages.appendChild(messageWrapper);
|
||||||
|
|
||||||
|
scrollToBottom();
|
||||||
|
}
|
||||||
|
|
||||||
|
function showBotTyping() {
|
||||||
|
const typingIndicator = document.createElement('div');
|
||||||
|
typingIndicator.id = 'typing-indicator';
|
||||||
|
typingIndicator.classList.add('message', 'bot-message');
|
||||||
|
|
||||||
|
const content = document.createElement('div');
|
||||||
|
content.classList.add('message-content');
|
||||||
|
|
||||||
|
const p = document.createElement('p');
|
||||||
|
p.textContent = '...';
|
||||||
|
|
||||||
|
content.appendChild(p);
|
||||||
|
typingIndicator.appendChild(content);
|
||||||
|
chatMessages.appendChild(typingIndicator);
|
||||||
|
scrollToBottom();
|
||||||
|
}
|
||||||
|
|
||||||
|
function removeBotTyping() {
|
||||||
|
const typingIndicator = document.getElementById('typing-indicator');
|
||||||
|
if (typingIndicator) {
|
||||||
|
typingIndicator.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function scrollToBottom() {
|
||||||
|
chatMessages.scrollTop = chatMessages.scrollHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initial scroll to bottom if content is already there
|
||||||
|
scrollToBottom();
|
||||||
|
});
|
||||||
1
db/knowledge_base.txt
Normal file
1
db/knowledge_base.txt
Normal file
@ -0,0 +1 @@
|
|||||||
|
Это БАЗА знаний 1. Введение в систему HUB Цель: Понять назначение HUB и его роль в управлении складскими данными. HUB — это система для управления складскими предметами (грузами, контейнерами, коробками и т.д.) и процессами их перемещения, хранения и инвентаризации. Она позволяет отслеживать состояние предметов, их историю, взаимодействие с контейнерами и логистическими точками, а также проводить пересчеты и настраивать складскую инфраструктуру. Ключевые понятия: Предмет: Объект хранения (например, ТЯ, коробка, отправление). Логистический контейнер (ЛК): Емкость для хранения/перемещения предметов (статусы: "Формируется", "Сформирован" и др.). Инвентаризация/пересчет: Проверка фактического наличия предметов на складе против учетных данных. КМО: Внутренний термин, предположительно связанный с документацией о материальных ошибках/недостачах (например, "Книга Материальных Остатков"). ЦМН: Цель доставки (место назначения предмета). Тайм-слот: Временной интервал для доставки. 2. Основы интерфейса HUB и карточка предмета Цель: Знакомство с интерфейсом HUB и структурой карточки предмета. HUB содержит главное меню, схему склада и таблицу со списком предметов. Основная работа ведется через карточку предмета — детализированное окно с информацией о конкретном объекте. 2.1 Структура карточки предмета Карточка доступна при клике на ID предмета в таблице "Предметы". Она включает следующие вкладки: Вкладка Описание Основные данные «О предмете» Основная информация о предмете. Тип, статус, ID, номенклатура, принадлежность, стоимость, адрес хранения. «Состав» Текущий и исторический состав контейнера (для предметов, являющихся контейнерами). Список предметов внутри, даты добавления/удаления, статусы элементов состава. «История (перемещения)» История перемещений предмета между ячейками, контейнерами и логистическими точками. Тип события (принято, перемещено, вошло/вышло из контейнера), дата, источник/цель. «Отгрузки» Запись о выдаче предмета (отгрузке) со склада. Дата отгрузки, получате
|
||||||
178
index.php
178
index.php
@ -1,131 +1,59 @@
|
|||||||
<?php
|
<!DOCTYPE html>
|
||||||
declare(strict_types=1);
|
<html lang="ru">
|
||||||
@ini_set('display_errors', '1');
|
|
||||||
@error_reporting(E_ALL);
|
|
||||||
@date_default_timezone_set('UTC');
|
|
||||||
|
|
||||||
$phpVersion = PHP_VERSION;
|
|
||||||
$now = date('Y-m-d H:i:s');
|
|
||||||
?>
|
|
||||||
<!doctype html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8" />
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<title>New Style</title>
|
<title>Your Logistic Koresh</title>
|
||||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
<meta name="description" content="AI Assistant for HUB System">
|
||||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
<meta name="robots" content="noindex, nofollow">
|
||||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;700&display=swap" rel="stylesheet">
|
|
||||||
<style>
|
<!-- Open Graph -->
|
||||||
:root {
|
<meta property="og:title" content="Your Logistic Koresh">
|
||||||
--bg-color-start: #6a11cb;
|
<meta property="og:description" content="AI Assistant for HUB System">
|
||||||
--bg-color-end: #2575fc;
|
<meta property="og:type" content="website">
|
||||||
--text-color: #ffffff;
|
<meta property="og:url" content=""> <!-- Will be the current URL -->
|
||||||
--card-bg-color: rgba(255, 255, 255, 0.01);
|
|
||||||
--card-border-color: rgba(255, 255, 255, 0.1);
|
<!-- Fonts -->
|
||||||
}
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||||
body {
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||||
margin: 0;
|
<link href="https://fonts.googleapis.com/css2?family=Roboto+Mono:wght@400;500&display=swap" rel="stylesheet">
|
||||||
font-family: 'Inter', sans-serif;
|
|
||||||
background: linear-gradient(45deg, var(--bg-color-start), var(--bg-color-end));
|
<!-- Bootstrap CSS -->
|
||||||
color: var(--text-color);
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous">
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
<!-- Custom CSS -->
|
||||||
align-items: center;
|
<link rel="stylesheet" href="assets/css/custom.css?v=<?php echo time(); ?>">
|
||||||
min-height: 100vh;
|
|
||||||
text-align: center;
|
|
||||||
overflow: hidden;
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
body::before {
|
|
||||||
content: '';
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100" viewBox="0 0 100 100"><path d="M-10 10L110 10M10 -10L10 110" stroke-width="1" stroke="rgba(255,255,255,0.05)"/></svg>');
|
|
||||||
animation: bg-pan 20s linear infinite;
|
|
||||||
z-index: -1;
|
|
||||||
}
|
|
||||||
@keyframes bg-pan {
|
|
||||||
0% { background-position: 0% 0%; }
|
|
||||||
100% { background-position: 100% 100%; }
|
|
||||||
}
|
|
||||||
main {
|
|
||||||
padding: 2rem;
|
|
||||||
}
|
|
||||||
.card {
|
|
||||||
background: var(--card-bg-color);
|
|
||||||
border: 1px solid var(--card-border-color);
|
|
||||||
border-radius: 16px;
|
|
||||||
padding: 2rem;
|
|
||||||
backdrop-filter: blur(20px);
|
|
||||||
-webkit-backdrop-filter: blur(20px);
|
|
||||||
box-shadow: 0 8px 32px 0 rgba(0, 0, 0, 0.1);
|
|
||||||
}
|
|
||||||
.loader {
|
|
||||||
margin: 1.25rem auto 1.25rem;
|
|
||||||
width: 48px;
|
|
||||||
height: 48px;
|
|
||||||
border: 3px solid rgba(255, 255, 255, 0.25);
|
|
||||||
border-top-color: #fff;
|
|
||||||
border-radius: 50%;
|
|
||||||
animation: spin 1s linear infinite;
|
|
||||||
}
|
|
||||||
@keyframes spin {
|
|
||||||
from { transform: rotate(0deg); }
|
|
||||||
to { transform: rotate(360deg); }
|
|
||||||
}
|
|
||||||
.hint {
|
|
||||||
opacity: 0.9;
|
|
||||||
}
|
|
||||||
.sr-only {
|
|
||||||
position: absolute;
|
|
||||||
width: 1px; height: 1px;
|
|
||||||
padding: 0; margin: -1px;
|
|
||||||
overflow: hidden;
|
|
||||||
clip: rect(0, 0, 0, 0);
|
|
||||||
white-space: nowrap; border: 0;
|
|
||||||
}
|
|
||||||
h1 {
|
|
||||||
font-size: 3rem;
|
|
||||||
font-weight: 700;
|
|
||||||
margin: 0 0 1rem;
|
|
||||||
letter-spacing: -1px;
|
|
||||||
}
|
|
||||||
p {
|
|
||||||
margin: 0.5rem 0;
|
|
||||||
font-size: 1.1rem;
|
|
||||||
}
|
|
||||||
code {
|
|
||||||
background: rgba(0,0,0,0.2);
|
|
||||||
padding: 2px 6px;
|
|
||||||
border-radius: 4px;
|
|
||||||
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
|
|
||||||
}
|
|
||||||
footer {
|
|
||||||
position: absolute;
|
|
||||||
bottom: 1rem;
|
|
||||||
font-size: 0.8rem;
|
|
||||||
opacity: 0.7;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<main>
|
|
||||||
<div class="card">
|
<div class="chat-container">
|
||||||
<h1>Analyzing your requirements and generating your website…</h1>
|
<header class="chat-header">
|
||||||
<div class="loader" role="status" aria-live="polite" aria-label="Applying initial changes">
|
<h1>Your Logistic Koresh</h1>
|
||||||
<span class="sr-only">Loading…</span>
|
<p class="text-muted">AI Assistant for HUB System</p>
|
||||||
</div>
|
</header>
|
||||||
<p class="hint"><?= ($_SERVER['HTTP_HOST'] ?? '') === 'appwizzy.com' ? 'AppWiZZy' : 'Flatlogic' ?> AI is collecting your requirements and applying the first changes.</p>
|
|
||||||
<p class="hint">This page will update automatically as the plan is implemented.</p>
|
<main class="chat-messages" id="chat-messages">
|
||||||
<p>Runtime: PHP <code><?= htmlspecialchars($phpVersion) ?></code> — UTC <code><?= htmlspecialchars($now) ?></code></p>
|
<!-- Messages will be appended here by JS -->
|
||||||
|
<div class="message bot-message">
|
||||||
|
<div class="message-content">
|
||||||
|
<p>Привет. Я — твой логистический кореш. Я здесь, чтобы помочь тебе с вопросами по системе HUB. Спрашивай, не стесняйся.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<footer class="chat-input-area">
|
||||||
|
<form id="chat-form" class="d-flex">
|
||||||
|
<input type="text" id="message-input" class="form-control" placeholder="Введите ваш вопрос..." autocomplete="off" required>
|
||||||
|
<button type="submit" class="btn btn-primary" id="send-button">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-send"><line x1="22" y1="2" x2="11" y2="13"></line><polygon points="22 2 15 22 11 13 2 9 22 2"></polygon></svg>
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
</footer>
|
||||||
</div>
|
</div>
|
||||||
</main>
|
|
||||||
<footer>
|
<!-- Bootstrap JS -->
|
||||||
Page updated: <?= htmlspecialchars($now) ?> (UTC)
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-YvpcrYf0tY3lHB60NNkmXc5s9fDVZLESaAA55NDzOxhy9GkcIdslK1eN7N6jIeHz" crossorigin="anonymous"></script>
|
||||||
</footer>
|
<!-- Custom JS -->
|
||||||
|
<script src="assets/js/main.js?v=<?php echo time(); ?>"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
Loading…
x
Reference in New Issue
Block a user