534 lines
16 KiB
HTML
534 lines
16 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="ru" data-theme="light">
|
||
<head>
|
||
<meta charset="utf-8">
|
||
<meta name="viewport" content="width=device-width,initial-scale=1">
|
||
<title>HR Candidate Matcher</title>
|
||
<link rel="stylesheet" href="design-system/kt-ai-fonts.css">
|
||
<link rel="stylesheet" href="design-system/kt-ai-tokens.css">
|
||
<link rel="stylesheet" href="design-system/kt-ai-components.css">
|
||
<link rel="stylesheet" href="design-system/kt-ai-page.css">
|
||
<link rel="icon" href="design-system/brand/kt-ai-logo.png">
|
||
<style>
|
||
a.kt-ai-btn { text-decoration: none; }
|
||
|
||
:root {
|
||
--hm-bg: var(--kt-ai-bg);
|
||
--hm-surface: var(--kt-ai-card-bg);
|
||
--hm-fg: var(--kt-ai-fg);
|
||
--hm-fg-muted: var(--kt-ai-fg-muted);
|
||
--hm-accent: var(--kt-ai-primary);
|
||
--hm-border: var(--kt-ai-border);
|
||
--hm-success: var(--kt-ai-primary);
|
||
--hm-warning: var(--kt-ai-fg-muted);
|
||
--hm-error: var(--kt-ai-danger);
|
||
}
|
||
|
||
.hm-container {
|
||
max-width: 1200px;
|
||
margin: 0 auto;
|
||
padding: var(--kt-ai-space-8);
|
||
}
|
||
|
||
.hm-header {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: var(--kt-ai-space-4);
|
||
margin-bottom: var(--kt-ai-space-8);
|
||
padding: var(--kt-ai-space-4) 0;
|
||
border-bottom: 1px solid var(--kt-ai-border);
|
||
}
|
||
|
||
.hm-title {
|
||
font-size: var(--kt-ai-text-xl);
|
||
font-weight: var(--kt-ai-weight-semibold);
|
||
}
|
||
|
||
.hm-nav {
|
||
display: flex;
|
||
gap: var(--kt-ai-space-2);
|
||
margin-left: auto;
|
||
}
|
||
|
||
.hm-nav-btn {
|
||
padding: var(--kt-ai-space-2) var(--kt-ai-space-3);
|
||
border-radius: var(--kt-ai-radius-md);
|
||
background: transparent;
|
||
border: 1px solid transparent;
|
||
color: var(--kt-ai-fg-muted);
|
||
cursor: pointer;
|
||
font-size: var(--kt-ai-text-sm);
|
||
transition: all 0.15s ease;
|
||
}
|
||
|
||
.hm-nav-btn:hover {
|
||
background: var(--kt-ai-card-bg);
|
||
color: var(--kt-ai-fg);
|
||
}
|
||
|
||
.hm-nav-btn.active {
|
||
background: var(--kt-ai-primary);
|
||
color: white;
|
||
}
|
||
|
||
.hm-screen {
|
||
display: none;
|
||
}
|
||
|
||
.hm-screen.active {
|
||
display: block;
|
||
}
|
||
|
||
.hm-card {
|
||
background: var(--kt-ai-card-bg);
|
||
border: 1px solid var(--kt-ai-card-border);
|
||
border-radius: var(--kt-ai-radius-xl);
|
||
padding: var(--kt-ai-space-6);
|
||
margin-bottom: var(--kt-ai-space-6);
|
||
}
|
||
|
||
.hm-grid-2 {
|
||
display: grid;
|
||
grid-template-columns: 1fr 1fr;
|
||
gap: var(--kt-ai-space-6);
|
||
}
|
||
|
||
.hm-label {
|
||
display: block;
|
||
font-size: var(--kt-ai-text-sm);
|
||
font-weight: var(--kt-ai-weight-medium);
|
||
margin-bottom: var(--kt-ai-space-2);
|
||
}
|
||
|
||
.hm-textarea {
|
||
width: 100%;
|
||
min-height: 280px;
|
||
padding: var(--kt-ai-space-3);
|
||
border: 1px solid var(--kt-ai-border);
|
||
border-radius: var(--kt-ai-radius-md);
|
||
font-family: var(--kt-ai-font-mono);
|
||
font-size: var(--kt-ai-text-sm);
|
||
line-height: 1.6;
|
||
resize: vertical;
|
||
background: var(--kt-ai-bg-soft);
|
||
color: var(--kt-ai-fg);
|
||
}
|
||
|
||
.hm-textarea:focus {
|
||
outline: 2px solid var(--kt-ai-primary);
|
||
border-color: transparent;
|
||
}
|
||
|
||
.hm-hint {
|
||
font-size: var(--kt-ai-text-xs);
|
||
color: var(--kt-ai-fg-muted);
|
||
margin-top: var(--kt-ai-space-2);
|
||
display: flex;
|
||
align-items: center;
|
||
gap: var(--kt-ai-space-1);
|
||
}
|
||
|
||
.hm-actions {
|
||
display: flex;
|
||
gap: var(--kt-ai-space-3);
|
||
margin-top: var(--kt-ai-space-6);
|
||
}
|
||
|
||
.hm-criteria-list {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: var(--kt-ai-space-3);
|
||
}
|
||
|
||
.hm-criterion {
|
||
display: grid;
|
||
grid-template-columns: 2fr 1fr 80px 40px;
|
||
gap: var(--kt-ai-space-3);
|
||
align-items: center;
|
||
padding: var(--kt-ai-space-3);
|
||
background: var(--kt-ai-bg-soft);
|
||
border-radius: var(--kt-ai-radius-md);
|
||
border: 1px solid var(--kt-ai-border);
|
||
}
|
||
|
||
.hm-criterion input[type="text"],
|
||
.hm-criterion select,
|
||
.hm-criterion input[type="number"] {
|
||
width: 100%;
|
||
padding: var(--kt-ai-space-2);
|
||
border: 1px solid var(--kt-ai-border);
|
||
border-radius: var(--kt-ai-radius-md);
|
||
background: var(--kt-ai-card-bg);
|
||
color: var(--kt-ai-fg);
|
||
font-size: var(--kt-ai-text-sm);
|
||
}
|
||
|
||
.hm-criterion input[type="number"] {
|
||
text-align: center;
|
||
}
|
||
|
||
.hm-criterion button {
|
||
width: 32px;
|
||
height: 32px;
|
||
border: none;
|
||
background: transparent;
|
||
color: var(--kt-ai-fg-muted);
|
||
cursor: pointer;
|
||
border-radius: var(--kt-ai-radius-md);
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
}
|
||
|
||
.hm-criterion button:hover {
|
||
background: var(--kt-ai-danger);
|
||
color: white;
|
||
}
|
||
|
||
.hm-synonyms {
|
||
grid-column: 1 / -1;
|
||
display: flex;
|
||
gap: var(--kt-ai-space-2);
|
||
align-items: center;
|
||
}
|
||
|
||
.hm-synonyms input {
|
||
flex: 1;
|
||
padding: var(--kt-ai-space-2);
|
||
border: 1px dashed var(--kt-ai-border);
|
||
border-radius: var(--kt-ai-radius-md);
|
||
background: var(--kt-ai-card-bg);
|
||
color: var(--kt-ai-fg);
|
||
font-size: var(--kt-ai-text-xs);
|
||
}
|
||
|
||
.hm-table-wrapper {
|
||
overflow-x: auto;
|
||
border: 1px solid var(--kt-ai-border);
|
||
border-radius: var(--kt-ai-radius-xl);
|
||
background: var(--kt-ai-card-bg);
|
||
}
|
||
|
||
.hm-table {
|
||
width: 100%;
|
||
border-collapse: collapse;
|
||
font-size: var(--kt-ai-text-sm);
|
||
}
|
||
|
||
.hm-table th {
|
||
text-align: left;
|
||
padding: var(--kt-ai-space-3) var(--kt-ai-space-4);
|
||
background: var(--kt-ai-bg-soft);
|
||
border-bottom: 2px solid var(--kt-ai-border);
|
||
font-weight: var(--kt-ai-weight-semibold);
|
||
white-space: nowrap;
|
||
}
|
||
|
||
.hm-table td {
|
||
padding: var(--kt-ai-space-3) var(--kt-ai-space-4);
|
||
border-bottom: 1px solid var(--kt-ai-border);
|
||
vertical-align: top;
|
||
}
|
||
|
||
.hm-table tr:last-child td {
|
||
border-bottom: none;
|
||
}
|
||
|
||
.hm-quote {
|
||
font-family: var(--kt-ai-font-mono);
|
||
font-size: var(--kt-ai-text-xs);
|
||
background: var(--kt-ai-bg-soft);
|
||
padding: var(--kt-ai-space-2);
|
||
border-radius: var(--kt-ai-radius-md);
|
||
border-left: 3px solid var(--kt-ai-primary);
|
||
max-width: 400px;
|
||
white-space: pre-wrap;
|
||
word-break: break-word;
|
||
}
|
||
|
||
.hm-status {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
gap: var(--kt-ai-space-1);
|
||
padding: var(--kt-ai-space-1) var(--kt-ai-space-2);
|
||
border-radius: var(--kt-ai-radius-full);
|
||
font-size: var(--kt-ai-text-xs);
|
||
font-weight: var(--kt-ai-weight-medium);
|
||
white-space: nowrap;
|
||
}
|
||
|
||
.hm-status-confirmed {
|
||
background: var(--kt-ai-bg-soft);
|
||
color: var(--kt-ai-primary);
|
||
}
|
||
|
||
.hm-status-clarify {
|
||
background: var(--kt-ai-bg-soft);
|
||
color: var(--kt-ai-fg-muted);
|
||
}
|
||
|
||
.hm-status-notfound {
|
||
background: var(--kt-ai-bg-soft);
|
||
color: var(--kt-ai-fg-muted);
|
||
}
|
||
|
||
.hm-coverage-bar {
|
||
height: 8px;
|
||
background: var(--kt-ai-border);
|
||
border-radius: var(--kt-ai-radius-full);
|
||
overflow: hidden;
|
||
margin-top: var(--kt-ai-space-4);
|
||
}
|
||
|
||
.hm-coverage-fill {
|
||
height: 100%;
|
||
background: var(--kt-ai-primary);
|
||
transition: width 0.3s ease;
|
||
}
|
||
|
||
.hm-coverage-text {
|
||
text-align: center;
|
||
font-size: var(--kt-ai-text-sm);
|
||
color: var(--kt-ai-fg-muted);
|
||
margin-top: var(--kt-ai-space-2);
|
||
}
|
||
|
||
.hm-questions-list {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: var(--kt-ai-space-4);
|
||
}
|
||
|
||
.hm-question-card {
|
||
background: var(--kt-ai-bg-soft);
|
||
border: 1px solid var(--kt-ai-border);
|
||
border-radius: var(--kt-ai-radius-md);
|
||
padding: var(--kt-ai-space-4);
|
||
}
|
||
|
||
.hm-question-criterion {
|
||
font-size: var(--kt-ai-text-sm);
|
||
font-weight: var(--kt-ai-weight-semibold);
|
||
margin-bottom: var(--kt-ai-space-2);
|
||
}
|
||
|
||
.hm-question-text {
|
||
font-size: var(--kt-ai-text-sm);
|
||
color: var(--kt-ai-fg-muted);
|
||
line-height: 1.6;
|
||
}
|
||
|
||
.hm-copy-area {
|
||
background: var(--kt-ai-card-bg);
|
||
border: 1px solid var(--kt-ai-border);
|
||
border-radius: var(--kt-ai-radius-md);
|
||
padding: var(--kt-ai-space-4);
|
||
font-family: var(--kt-ai-font-mono);
|
||
font-size: var(--kt-ai-text-sm);
|
||
white-space: pre-wrap;
|
||
max-height: 300px;
|
||
overflow-y: auto;
|
||
margin-top: var(--kt-ai-space-4);
|
||
}
|
||
|
||
.hm-empty {
|
||
text-align: center;
|
||
padding: var(--kt-ai-space-12) var(--kt-ai-space-6);
|
||
color: var(--kt-ai-fg-muted);
|
||
}
|
||
|
||
.hm-empty-icon {
|
||
width: 64px;
|
||
height: 64px;
|
||
margin: 0 auto var(--kt-ai-space-4);
|
||
color: var(--kt-ai-border);
|
||
}
|
||
|
||
.hm-brand img {
|
||
height: 20px;
|
||
}
|
||
|
||
@media (max-width: 768px) {
|
||
.hm-grid-2 {
|
||
grid-template-columns: 1fr;
|
||
}
|
||
|
||
.hm-criterion {
|
||
grid-template-columns: 1fr;
|
||
gap: var(--kt-ai-space-2);
|
||
}
|
||
|
||
.hm-header {
|
||
flex-wrap: wrap;
|
||
}
|
||
|
||
.hm-nav {
|
||
margin-left: 0;
|
||
width: 100%;
|
||
overflow-x: auto;
|
||
}
|
||
|
||
.hm-container {
|
||
padding: var(--kt-ai-space-4);
|
||
}
|
||
}
|
||
</style>
|
||
</head>
|
||
<body>
|
||
|
||
<div class="hm-container">
|
||
<header class="hm-header">
|
||
<a class="kt-ai-brand" href="#">
|
||
<img src="design-system/brand/kazakhtelecom-logo.png" alt="Казахтелеком" height="20">
|
||
</a>
|
||
<span class="hm-title">HR Candidate Matcher</span>
|
||
<nav class="hm-nav" id="hmNav">
|
||
<button class="hm-nav-btn" data-screen="input">Ввод</button>
|
||
<button class="hm-nav-btn" data-screen="criteria">Критерии</button>
|
||
<button class="hm-nav-btn" data-screen="match">Сопоставление</button>
|
||
<button class="hm-nav-btn" data-screen="interview">Интервью</button>
|
||
</nav>
|
||
</header>
|
||
|
||
<main>
|
||
<!-- ЭКРАН ВВОДА -->
|
||
<section id="screen-input" class="hm-screen active">
|
||
<div class="hm-card">
|
||
<h1 style="margin-bottom: var(--kt-ai-space-2)">Сопоставление резюме и вакансии</h1>
|
||
<p style="color: var(--kt-ai-fg-muted); margin-bottom: var(--kt-ai-space-6)">
|
||
Вставьте текст вакансии и резюме — система извлечёт требования и покажет степень соответствия.
|
||
</p>
|
||
|
||
<div class="hm-grid-2">
|
||
<div>
|
||
<label class="hm-label" for="vacancyText">Текст вакансии</label>
|
||
<textarea id="vacancyText" class="hm-textarea" placeholder="Требования, обязанности, условия..."></textarea>
|
||
</div>
|
||
<div>
|
||
<label class="hm-label" for="resumeText">Текст резюме (обезличенное)</label>
|
||
<textarea id="resumeText" class="hm-textarea" placeholder="Опыт, навыки, образование..."></textarea>
|
||
<div class="hm-hint">
|
||
<svg class="kt-icon kt-icon-sm" aria-hidden="true"><use href="#lock"></use></svg>
|
||
Данные не покидают браузер и не сохраняются без вашего согласия
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="hm-actions">
|
||
<button class="kt-ai-btn" data-variant="primary" id="btnExtract">
|
||
<svg class="kt-icon kt-icon-sm" style="margin-right: var(--kt-ai-space-2)"><use href="#sparkles"></use></svg>
|
||
Извлечь требования
|
||
</button>
|
||
<button class="kt-ai-btn" id="btnLoadExample">Попробовать пример</button>
|
||
<button class="kt-ai-btn" data-variant="ghost" id="btnClearAll" style="margin-left: auto">
|
||
<svg class="kt-icon kt-icon-sm" style="margin-right: var(--kt-ai-space-2)"><use href="#trash"></use></svg>
|
||
Очистить всё
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- ЭКРАН КРИТЕРИЕВ -->
|
||
<section id="screen-criteria" class="hm-screen">
|
||
<div class="hm-card">
|
||
<h1 style="margin-bottom: var(--kt-ai-space-2)">Критерии оценки</h1>
|
||
<p style="color: var(--kt-ai-fg-muted); margin-bottom: var(--kt-ai-space-6)">
|
||
Отредактируйте требования: укажите обязательность, вес (1–5) и синонимы для поиска.
|
||
</p>
|
||
|
||
<div id="criteriaList" class="hm-criteria-list"></div>
|
||
|
||
<div class="hm-actions">
|
||
<button class="kt-ai-btn" id="btnAddCriterion">
|
||
<svg class="kt-icon kt-icon-sm" style="margin-right: var(--kt-ai-space-2)"><use href="#plus"></use></svg>
|
||
Добавить критерий
|
||
</button>
|
||
<button class="kt-ai-btn" data-variant="primary" id="btnApplyCriteria" style="margin-left: auto">
|
||
Применить и перейти к сопоставлению
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- ЭКРАН СОПОСТАВЛЕНИЯ -->
|
||
<section id="screen-match" class="hm-screen">
|
||
<div class="hm-card">
|
||
<h1 style="margin-bottom: var(--kt-ai-space-2)">Сопоставление требований</h1>
|
||
<p style="color: var(--kt-ai-fg-muted); margin-bottom: var(--kt-ai-space-6)">
|
||
Система нашла соответствия в резюме для каждого требования.
|
||
</p>
|
||
|
||
<div id="matchResults">
|
||
<div class="hm-table-wrapper">
|
||
<table class="hm-table">
|
||
<thead>
|
||
<tr>
|
||
<th style="width: 25%">Требование</th>
|
||
<th style="width: 15%">Тип</th>
|
||
<th style="width: 15%">Вес</th>
|
||
<th style="width: 30%">Найдено в резюме</th>
|
||
<th style="width: 15%">Статус</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody id="matchTableBody"></tbody>
|
||
</table>
|
||
</div>
|
||
|
||
<div class="hm-coverage-bar">
|
||
<div class="hm-coverage-fill" id="coverageFill" style="width: 0%"></div>
|
||
</div>
|
||
<div class="hm-coverage-text" id="coverageText">Покрытие требований: 0%</div>
|
||
</div>
|
||
|
||
<div id="matchEmpty" class="hm-empty" style="display: none">
|
||
<svg class="hm-empty-icon" aria-hidden="true"><use href="#search"></use></svg>
|
||
<h3>Ничего не найдено</h3>
|
||
<p>Попробуйте изменить критерии или добавить синонимы</p>
|
||
</div>
|
||
|
||
<div class="hm-actions">
|
||
<button class="kt-ai-btn" id="btnBackToCriteria">Назад к критериям</button>
|
||
<button class="kt-ai-btn" data-variant="primary" id="btnGenerateQuestions" style="margin-left: auto">
|
||
<svg class="kt-icon kt-icon-sm" style="margin-right: var(--kt-ai-space-2)"><use href="#sparkles"></use></svg>
|
||
Сгенерировать вопросы
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- ЭКРАН ИНТЕРВЬЮ -->
|
||
<section id="screen-interview" class="hm-screen">
|
||
<div class="hm-card">
|
||
<h1 style="margin-bottom: var(--kt-ai-space-2)">Вопросы для интервью</h1>
|
||
<p style="color: var(--kt-ai-fg-muted); margin-bottom: var(--kt-ai-space-6)">
|
||
Вопросы по требованиям, которые требуют уточнения на собеседовании.
|
||
</p>
|
||
|
||
<div id="questionsList" class="hm-questions-list"></div>
|
||
|
||
<div class="hm-actions">
|
||
<button class="kt-ai-btn" id="btnBackToMatch">Назад к сопоставлению</button>
|
||
<button class="kt-ai-btn" id="btnCopyQuestions">
|
||
<svg class="kt-icon kt-icon-sm" style="margin-right: var(--kt-ai-space-2)"><use href="#copy"></use></svg>
|
||
Копировать вопросы
|
||
</button>
|
||
<button class="kt-ai-btn" data-variant="primary" id="btnExport" style="margin-left: auto">
|
||
<svg class="kt-icon kt-icon-sm" style="margin-right: var(--kt-ai-space-2)"><use href="#download"></use></svg>
|
||
Экспорт сводки
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
</main>
|
||
</div>
|
||
|
||
<script src="design-system/icons/kt-ai-icons.js"></script>
|
||
<script src="aiAdapter.js"></script>
|
||
<script src="storage.js"></script>
|
||
<script src="matcher.js"></script>
|
||
<script src="ui.js"></script>
|
||
<script src="app.js"></script>
|
||
|
||
</body>
|
||
</html>
|