work-license-server 1.0.2 → 1.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -2
- package/assets/admin.js +572 -0
- package/assets/landing.css +113 -1
- package/assets/landing.js +322 -290
- package/bin/server.mjs +5 -2
- package/package.json +1 -1
- package/src/admin.js +319 -0
- package/src/agent.js +152 -8
- package/src/bots.js +1 -1
- package/src/catalog.js +153 -17
- package/src/crypto.js +249 -17
- package/src/index.js +22 -1
- package/src/landing.js +113 -141
- package/src/server.js +229 -24
- package/src/store.js +696 -50
- package/src/yookassa.js +22 -8
package/src/landing.js
CHANGED
|
@@ -16,6 +16,7 @@ import {
|
|
|
16
16
|
FRANCHISE_PROGRAM,
|
|
17
17
|
REGIONS_CATALOG,
|
|
18
18
|
PARTNER_TRAINING_TRACKS,
|
|
19
|
+
PUBLIC_OFERTA,
|
|
19
20
|
} from './catalog.js';
|
|
20
21
|
|
|
21
22
|
const ICON_PATHS = {
|
|
@@ -50,6 +51,7 @@ const ICON_PATHS = {
|
|
|
50
51
|
image: 'M4 5h16v14H4z M4 16l5-5 4 4 3-3 4 4 M15 9h.01',
|
|
51
52
|
search: 'M11 4a7 7 0 1 0 0 14a7 7 0 1 0 0-14 M20 20l-4-4',
|
|
52
53
|
key: 'M8 14a4 4 0 1 0 0-8a4 4 0 1 0 0 8 M11 10h10 M17 10v4 M20 10v3',
|
|
54
|
+
cart: 'M4 5h2l2.4 9.5a2 2 0 0 0 2 1.5h7.2a2 2 0 0 0 1.9-1.4L21 8H7 M9 20a1 1 0 1 0 0-2a1 1 0 1 0 0 2 M18 20a1 1 0 1 0 0-2a1 1 0 1 0 0 2',
|
|
53
55
|
};
|
|
54
56
|
|
|
55
57
|
export function icon(name) {
|
|
@@ -139,6 +141,7 @@ export function renderLandingPage({ publicKey = '', regions = null, assetVersion
|
|
|
139
141
|
districts: FEDERAL_DISTRICTS,
|
|
140
142
|
ai: AI_PLATFORM,
|
|
141
143
|
vendor: VENDOR_CONTACTS,
|
|
144
|
+
oferta: PUBLIC_OFERTA,
|
|
142
145
|
icons: ICON_PATHS,
|
|
143
146
|
initialStage,
|
|
144
147
|
};
|
|
@@ -188,8 +191,8 @@ export function renderLandingPage({ publicKey = '', regions = null, assetVersion
|
|
|
188
191
|
|
|
189
192
|
<div class="top-actions">
|
|
190
193
|
<button class="icon-btn" id="btnTheme" onclick="toggleTheme()" title="Светлая / тёмная тема" aria-label="Переключить тему">${icon('sun')}</button>
|
|
191
|
-
<button class="btn btn-ghost btn-sm"
|
|
192
|
-
<button class="btn btn-ghost btn-sm" id="btnAuth" data-action="auth">${icon('user')}<span id="btnAuthText"
|
|
194
|
+
<button class="btn btn-ghost btn-sm" data-action="open-oferta" title="Публичный договор-оферта ODANT-WORK">${icon('docs')}<span>Оферта</span></button>
|
|
195
|
+
<button class="btn btn-ghost btn-sm" id="btnAuth" data-action="auth">${icon('user')}<span id="btnAuthText">Войти / Регистрация</span></button>
|
|
193
196
|
<button class="btn btn-primary btn-sm" data-stage="order">Заказать</button>
|
|
194
197
|
</div>
|
|
195
198
|
</header>
|
|
@@ -207,8 +210,8 @@ export function renderLandingPage({ publicKey = '', regions = null, assetVersion
|
|
|
207
210
|
</div>
|
|
208
211
|
<div class="trust">
|
|
209
212
|
<span>${icon('shield')} Данные не покидают контур</span>
|
|
210
|
-
<span>${icon('key')}
|
|
211
|
-
<span>${icon('check')} 1 год поддержки
|
|
213
|
+
<span>${icon('key')} ${P.baseSeats} вечных лицензий</span>
|
|
214
|
+
<span>${icon('check')} 1 год поддержки Enterprise (далее — по желанию)</span>
|
|
212
215
|
</div>
|
|
213
216
|
</div>
|
|
214
217
|
<div class="showcase" aria-hidden="true">
|
|
@@ -250,7 +253,7 @@ export function renderLandingPage({ publicKey = '', regions = null, assetVersion
|
|
|
250
253
|
<span class="kicker">Паспорт комплекса</span>
|
|
251
254
|
<h2 class="h2">ODANT-WORK · ${esc(P.sku)}</h2>
|
|
252
255
|
<div class="price-big">${rub(P.basePriceRub)}</div>
|
|
253
|
-
<p class="note">Вечная лицензия на ${P.baseSeats} одновременных рабочих сессий, привязанная к оборудованию, и ${P.includedSupportYears} год поддержки уровня
|
|
256
|
+
<p class="note">Вечная лицензия на ${P.baseSeats} одновременных рабочих сессий, привязанная к оборудованию, и ${P.includedSupportYears} год максимальной поддержки уровня Enterprise (24/7, реакция ≤ 15 мин) — в комплекте. Дальнейшее продление поддержки и докупка мест — по желанию.</p>
|
|
254
257
|
<div class="hero-cta" style="margin-top:20px">
|
|
255
258
|
<button class="btn btn-primary" data-stage="order">Оформить заказ</button>
|
|
256
259
|
<button class="btn btn-ghost" data-stage="pricing">Тарифы поддержки</button>
|
|
@@ -270,12 +273,20 @@ export function renderLandingPage({ publicKey = '', regions = null, assetVersion
|
|
|
270
273
|
|
|
271
274
|
<div class="sec-head reveal">
|
|
272
275
|
<div>
|
|
273
|
-
<span class="kicker">Приватный
|
|
274
|
-
<h2 class="h2">Четыре типа моделей уже установлены</h2>
|
|
276
|
+
<span class="kicker">Приватный и гибридный ИИ</span>
|
|
277
|
+
<h2 class="h2">Четыре типа базовых моделей уже установлены</h2>
|
|
275
278
|
</div>
|
|
276
|
-
<p
|
|
279
|
+
<p>Интегрированные локальные модели предназначены для базовых ежедневных операций внутри контура. Если требуются более мощные модели ИИ, их можно подключить через API из любого источника.</p>
|
|
277
280
|
</div>
|
|
278
281
|
<div class="grid g4">${renderModels()}</div>
|
|
282
|
+
<div class="card reveal" style="display:flex;align-items:center;justify-content:space-between;gap:20px;flex-wrap:wrap">
|
|
283
|
+
<div>
|
|
284
|
+
<span class="kicker">Подключение мощных моделей ИИ по API</span>
|
|
285
|
+
<h3 class="h3" style="margin:4px 0 6px">Нужны более мощные модели? Подключайте из любого источника</h3>
|
|
286
|
+
<p class="note" style="margin:0">Предустановленные на комплексе модели закрывают базовые операции учёта, голоса, иллюстраций и поиска без внешних каналов. Для сложной аналитики, больших контекстов и специализированных агентов вы можете в один клик подключить по стандартному API модели из любого источника: внешних облачных провайдеров, корпоративного GPU-кластера или коммерческого API регионального партнёра.</p>
|
|
287
|
+
</div>
|
|
288
|
+
<button class="btn btn-ghost btn-sm" data-stage="agents">Подробнее об ИИ-агентах →</button>
|
|
289
|
+
</div>
|
|
279
290
|
</section>
|
|
280
291
|
|
|
281
292
|
<!-- ============ ИИ-АГЕНТЫ ============ -->
|
|
@@ -333,9 +344,9 @@ export function renderLandingPage({ publicKey = '', regions = null, assetVersion
|
|
|
333
344
|
<div class="sec-head">
|
|
334
345
|
<div>
|
|
335
346
|
<span class="kicker">Лицензии и поддержка</span>
|
|
336
|
-
<h2 class="h2"
|
|
347
|
+
<h2 class="h2">10 вечных лицензий + 1 год Enterprise в базе, дальше — по желанию</h2>
|
|
337
348
|
</div>
|
|
338
|
-
<p>${P.baseSeats} рабочих мест входят в комплекс
|
|
349
|
+
<p>${P.baseSeats} рабочих мест входят в комплекс навсегда вместе с 1-м годом поддержки уровня Enterprise. Дальнейшее продление поддержки и докупка годовых мест — по желанию. Считаются одновременные активные сессии, а не учётные записи.</p>
|
|
339
350
|
</div>
|
|
340
351
|
<div class="tiers">${renderTiers()}</div>
|
|
341
352
|
<div class="card">
|
|
@@ -351,10 +362,18 @@ export function renderLandingPage({ publicKey = '', regions = null, assetVersion
|
|
|
351
362
|
<section class="stage" id="stage-order">
|
|
352
363
|
<div class="sec-head">
|
|
353
364
|
<div><span class="kicker">Заказ</span><h2 class="h2">Программно-аппаратный комплекс ODANT-WORK</h2></div>
|
|
354
|
-
<p>Сервер AMD Ryzen™ AI Max+ PRO 495 · 192 ГБ · 4 ТБ с установленной платформой, вечной лицензией на ${P.baseSeats} мест и годом
|
|
365
|
+
<p>Сервер AMD Ryzen™ AI Max+ PRO 495 · 192 ГБ · 4 ТБ с установленной платформой, вечной лицензией на ${P.baseSeats} мест и 1 годом поддержки Enterprise (дальше — по желанию). Оплата через ЮKassa с чеком по 54-ФЗ.</p>
|
|
355
366
|
</div>
|
|
367
|
+
<div class="card oferta-banner" data-oferta-banner></div>
|
|
356
368
|
<div class="split">
|
|
357
369
|
<div class="card">
|
|
370
|
+
<div class="field">
|
|
371
|
+
<label>Вариант базовой поставки</label>
|
|
372
|
+
<div class="seg" id="segPakVariant">
|
|
373
|
+
<button data-variant="pak" class="on">Комплект с машиной<small>${rub(P.basePriceRub)} · железо + 10 мест</small></button>
|
|
374
|
+
<button data-variant="license_only">Базовая лицензия без железа<small>${rub(P.baseLicensePriceRub || 4_000_000)} · 10 вечных мест</small></button>
|
|
375
|
+
</div>
|
|
376
|
+
</div>
|
|
358
377
|
<div class="row2">
|
|
359
378
|
<div class="field"><label for="inpPakOrg">Организация</label><input type="text" id="inpPakOrg" value="ООО «Маслоторг»"></div>
|
|
360
379
|
<div class="field"><label for="inpPakInn">ИНН</label><input type="text" id="inpPakInn" value="7701234567" inputmode="numeric"></div>
|
|
@@ -368,24 +387,35 @@ export function renderLandingPage({ publicKey = '', regions = null, assetVersion
|
|
|
368
387
|
<label>Уровень поддержки дополнительных мест</label>
|
|
369
388
|
<div class="seg" id="segPakTier">${Object.values(SLA_TIERS).map(t => `<button data-tier="${t.id}" class="${t.id === 'business' ? 'on' : ''}">${esc(t.name)}<small>${rub(t.pricePerUserYearRub)}/год</small></button>`).join('')}</div>
|
|
370
389
|
</div>
|
|
371
|
-
<p class="note muted" style="margin:6px 0 0">Уже есть комплекс? <a href="#" data-action="addons">Войдите в
|
|
390
|
+
<p class="note muted" style="margin:6px 0 0">Уже есть комплекс? <a href="#" data-action="addons">Войдите в кабинет и подпишите оферту</a>, чтобы докупить места со скидкой или получить токен привязки.</p>
|
|
372
391
|
</div>
|
|
373
392
|
<div class="card summary card-glow">
|
|
374
393
|
<span class="kicker">Итого</span>
|
|
375
394
|
<div class="sum-total" id="lblPakTotal">${rub(P.basePriceRub)}</div>
|
|
376
395
|
<div class="sum-lines" id="lblPakBreakdown"></div>
|
|
377
396
|
<button class="btn btn-primary btn-lg" style="width:100%" data-action="order-pak">Оформить и оплатить через ЮKassa</button>
|
|
397
|
+
<button class="btn btn-ghost btn-sm" style="width:100%;margin-top:8px" data-action="order-pak-invoice">Выставить счёт-договор (для юр. лиц)</button>
|
|
378
398
|
<div class="status" id="pakOrderStatus"></div>
|
|
379
399
|
</div>
|
|
380
400
|
</div>
|
|
381
401
|
</section>
|
|
382
402
|
|
|
383
|
-
<!-- ============ ДОКУПКА ЛИЦЕНЗИЙ (только после входа) ============ -->
|
|
403
|
+
<!-- ============ ДОКУПКА ЛИЦЕНЗИЙ И ЛИЧНЫЙ КАБИНЕТ (только после входа и подписания оферты) ============ -->
|
|
384
404
|
<section class="stage" id="stage-addons">
|
|
385
405
|
<div class="sec-head">
|
|
386
|
-
<div><span class="kicker">Личный
|
|
406
|
+
<div><span class="kicker">Личный кабинет владельца</span><h2 class="h2">Токен привязки локальной системы и покупка лицензий</h2></div>
|
|
387
407
|
<p id="userBadgeBox"></p>
|
|
388
408
|
</div>
|
|
409
|
+
<div class="card oferta-banner" data-oferta-banner></div>
|
|
410
|
+
<div class="card" style="margin-bottom:20px">
|
|
411
|
+
<span class="kicker">Ключ доступа для локального сервера WORK</span>
|
|
412
|
+
<h3 class="h3" style="margin:4px 0 8px">Токен владельца (содержит URL сервера поддержки и ключ синхронизации лицензий)</h3>
|
|
413
|
+
<p class="small" style="margin:0 0 10px">Скопируйте этот токен и вставьте его в раздел «Лицензирование» вашей локальной системы ODANT-WORK. Система автоматически привяжется к личному кабинету и загрузит файлы лицензий в папку <code>#system</code>.</p>
|
|
414
|
+
<div style="display:flex;gap:10px;flex-wrap:wrap;align-items:center">
|
|
415
|
+
<input type="text" id="inpCabinetHubToken" readonly placeholder="owk1..." style="flex:1;min-width:260px;font-family:monospace">
|
|
416
|
+
<button class="btn btn-ghost btn-sm" data-action="gen-hub-token">Сгенерировать / Обновить токен</button>
|
|
417
|
+
</div>
|
|
418
|
+
</div>
|
|
389
419
|
<div class="split">
|
|
390
420
|
<div class="card">
|
|
391
421
|
<div class="field">
|
|
@@ -400,7 +430,7 @@ export function renderLandingPage({ publicKey = '', regions = null, assetVersion
|
|
|
400
430
|
<div class="seg" id="segTier">${Object.values(SLA_TIERS).map(t => `<button data-tier="${t.id}" class="${t.id === 'business' ? 'on' : ''}">${esc(t.name)}<small>${rub(t.pricePerUserYearRub)} · ${esc(t.reactionLabel)}</small></button>`).join('')}</div>
|
|
401
431
|
</div>
|
|
402
432
|
<div class="row2">
|
|
403
|
-
<div class="field"><label for="inpYears">Срок,
|
|
433
|
+
<div class="field"><label for="inpYears">Срок, лет (кратно годам)</label><input type="number" id="inpYears" min="1" max="5" value="1"></div>
|
|
404
434
|
<div class="field"><label for="inpLicId">Лицензия комплекса</label><input type="text" id="inpLicId" readonly></div>
|
|
405
435
|
</div>
|
|
406
436
|
<div class="field" style="margin-top:6px"><label>Скидка от количества</label>${renderLadder('ladderAddons')}</div>
|
|
@@ -411,6 +441,7 @@ export function renderLandingPage({ publicKey = '', regions = null, assetVersion
|
|
|
411
441
|
<div class="small" id="lblDiscountBadge" style="color:var(--ok);font-weight:650"></div>
|
|
412
442
|
<div class="sum-lines" id="lblBreakdown"></div>
|
|
413
443
|
<button class="btn btn-primary btn-lg" style="width:100%" data-action="order-addons">Оплатить через ЮKassa</button>
|
|
444
|
+
<button class="btn btn-ghost btn-sm" style="width:100%;margin-top:8px" data-action="order-addons-invoice">Выставить счёт-договор (для юр. лиц)</button>
|
|
414
445
|
<div class="status" id="orderStatus"></div>
|
|
415
446
|
</div>
|
|
416
447
|
</div>
|
|
@@ -422,6 +453,7 @@ export function renderLandingPage({ publicKey = '', regions = null, assetVersion
|
|
|
422
453
|
<div><span class="kicker">Партнёрская программа</span><h2 class="h2">Региональная франшиза ODANT-WORK</h2></div>
|
|
423
454
|
<p>Число франшиз в субъекте пропорционально населению, паушальный взнос — экономике региона. Резерв закрепляется сразу после невозвратного залога ${rub(FRANCHISE_PROGRAM.reservationDepositRub)}, полная оплата паушального взноса — в течение 1 года.</p>
|
|
424
455
|
</div>
|
|
456
|
+
<div class="card oferta-banner" data-oferta-banner></div>
|
|
425
457
|
<div class="stats">
|
|
426
458
|
<div class="stat"><b id="statVacant">${totalVacant}</b><span>вакантных франшиз</span></div>
|
|
427
459
|
<div class="stat"><b>${visibleRegions.length}</b><span>субъектов РФ</span></div>
|
|
@@ -559,14 +591,13 @@ export function renderLandingPage({ publicKey = '', regions = null, assetVersion
|
|
|
559
591
|
</div>
|
|
560
592
|
<div class="card">
|
|
561
593
|
<div style="display:flex;justify-content:space-between;align-items:center;gap:10px;flex-wrap:wrap">
|
|
562
|
-
<h3 class="h3" style="margin:0"
|
|
594
|
+
<h3 class="h3" style="margin:0">Ваша лицензия и привязка мессенджеров</h3>
|
|
563
595
|
<div style="display:flex;gap:8px;flex-wrap:wrap">
|
|
564
|
-
<button class="btn btn-ghost btn-sm" data-action="
|
|
565
|
-
<button class="btn btn-
|
|
566
|
-
<button class="btn btn-primary btn-sm" data-stage="admin">Открыть админку →</button>
|
|
596
|
+
<button class="btn btn-ghost btn-sm" data-action="auth">Личный кабинет</button>
|
|
597
|
+
<button class="btn btn-ghost btn-sm" data-action="open-oferta">Договор-оферта</button>
|
|
567
598
|
</div>
|
|
568
599
|
</div>
|
|
569
|
-
<div class="console" id="
|
|
600
|
+
<div class="console" id="clientLicenseBox" style="margin-top:14px">Войдите в личный кабинет и подпишите договор-оферту, чтобы получить код привязки вашего комплекса к ботам MAX, Telegram и VK.</div>
|
|
570
601
|
</div>
|
|
571
602
|
</div>
|
|
572
603
|
<div class="card">
|
|
@@ -585,131 +616,23 @@ export function renderLandingPage({ publicKey = '', regions = null, assetVersion
|
|
|
585
616
|
</div>
|
|
586
617
|
</section>
|
|
587
618
|
|
|
588
|
-
<!-- ============ АДМИНКА СЕРВЕРА ЛИЦЕНЗИЙ (/admin) ============ -->
|
|
589
|
-
<section class="stage" id="stage-admin">
|
|
590
|
-
<div class="sec-head">
|
|
591
|
-
<div>
|
|
592
|
-
<span class="kicker">Центр сертификации и биллинга · /admin</span>
|
|
593
|
-
<h2 class="h2">Админ-панель сервера лицензий ODANT-WORK</h2>
|
|
594
|
-
</div>
|
|
595
|
-
<div style="display:flex;gap:8px;flex-wrap:wrap">
|
|
596
|
-
<button class="btn btn-ghost btn-sm" data-action="registry">Обновить реестр</button>
|
|
597
|
-
<button class="btn btn-ok btn-sm" data-action="demo-pak">+ Демо-лицензия ПАК</button>
|
|
598
|
-
</div>
|
|
599
|
-
</div>
|
|
600
|
-
|
|
601
|
-
<div class="stats">
|
|
602
|
-
<div class="stat"><b id="admStatLic">0</b><span id="admStatLicSub">лицензий ПАК · 0 мест</span></div>
|
|
603
|
-
<div class="stat"><b id="admStatPaid">0 ₽</b><span id="admStatPaidSub">оплачено заказов: 0</span></div>
|
|
604
|
-
<div class="stat"><b id="admStatPending">0 ₽</b><span id="admStatPendingSub">ожидают оплаты: 0</span></div>
|
|
605
|
-
<div class="stat"><b id="admStatPartners">0 / 0</b><span>партнёров / резервов франшиз</span></div>
|
|
606
|
-
<div class="stat"><b id="admStatTickets">0</b><span id="admStatTicketsSub">открытых тикетов SLA</span></div>
|
|
607
|
-
</div>
|
|
608
|
-
|
|
609
|
-
<div class="card">
|
|
610
|
-
<div class="sec-head" style="margin-bottom:14px">
|
|
611
|
-
<div>
|
|
612
|
-
<span class="kicker">Выпуск сертификата Ed25519</span>
|
|
613
|
-
<h3 class="h3" style="margin:4px 0 0">Выпустить базовую лицензию комплекса (${P.baseSeats} вечных мест + 1 год поддержки)</h3>
|
|
614
|
-
</div>
|
|
615
|
-
</div>
|
|
616
|
-
<div class="grid g4" style="align-items:end">
|
|
617
|
-
<div class="field" style="margin:0"><label for="admLicOrg">Организация</label><input type="text" id="admLicOrg" value="АО «РязаньАгроПром»"></div>
|
|
618
|
-
<div class="field" style="margin:0"><label for="admLicInn">ИНН</label><input type="text" id="admLicInn" value="6234109876"></div>
|
|
619
|
-
<div class="field" style="margin:0"><label for="admLicEmail">Email клиента</label><input type="email" id="admLicEmail" value="it@ryazan-agro.ru"></div>
|
|
620
|
-
<div class="field" style="margin:0"><label for="admLicHwid">HWID комплекса (необязательно)</label><input type="text" id="admLicHwid" placeholder="WORK-HWID-..."></div>
|
|
621
|
-
</div>
|
|
622
|
-
<div style="display:flex;align-items:center;gap:14px;margin-top:14px;flex-wrap:wrap">
|
|
623
|
-
<button class="btn btn-primary btn-sm" data-action="adm-issue-lic">${icon('key')} Выпустить и подписать сертификат</button>
|
|
624
|
-
<span class="small muted" id="admIssueStatus"></span>
|
|
625
|
-
</div>
|
|
626
|
-
</div>
|
|
627
|
-
|
|
628
|
-
<div class="card">
|
|
629
|
-
<h3 class="h3" style="margin:0 0 12px">Выпущенные лицензии комплексов ODANT-WORK</h3>
|
|
630
|
-
<div class="table-wrap">
|
|
631
|
-
<table class="t">
|
|
632
|
-
<thead><tr>
|
|
633
|
-
<th>Лицензия / Код бота</th>
|
|
634
|
-
<th>Организация / ИНН</th>
|
|
635
|
-
<th>Привязка оборудования</th>
|
|
636
|
-
<th class="num">Сессии (вечные + доп.)</th>
|
|
637
|
-
<th>SLA и срок</th>
|
|
638
|
-
<th>Сертификат</th>
|
|
639
|
-
</tr></thead>
|
|
640
|
-
<tbody id="admLicensesBody"><tr><td colspan="6" class="muted">Загрузка…</td></tr></tbody>
|
|
641
|
-
</table>
|
|
642
|
-
</div>
|
|
643
|
-
</div>
|
|
644
|
-
|
|
645
|
-
<div class="card">
|
|
646
|
-
<h3 class="h3" style="margin:0 0 12px">Заказы и платежи ЮKassa</h3>
|
|
647
|
-
<div class="table-wrap">
|
|
648
|
-
<table class="t">
|
|
649
|
-
<thead><tr>
|
|
650
|
-
<th>Заказ / Платёж</th>
|
|
651
|
-
<th>Назначение</th>
|
|
652
|
-
<th>Плательщик</th>
|
|
653
|
-
<th class="num">Сумма</th>
|
|
654
|
-
<th>Статус</th>
|
|
655
|
-
<th>Действия</th>
|
|
656
|
-
</tr></thead>
|
|
657
|
-
<tbody id="admOrdersBody"><tr><td colspan="6" class="muted">Загрузка…</td></tr></tbody>
|
|
658
|
-
</table>
|
|
659
|
-
</div>
|
|
660
|
-
</div>
|
|
661
|
-
|
|
662
|
-
<div class="card">
|
|
663
|
-
<h3 class="h3" style="margin:0 0 12px">Резервы региональных франшиз и действующие партнёры</h3>
|
|
664
|
-
<div class="table-wrap">
|
|
665
|
-
<table class="t">
|
|
666
|
-
<thead><tr>
|
|
667
|
-
<th>ID / Тип</th>
|
|
668
|
-
<th>Субъект РФ</th>
|
|
669
|
-
<th>Компания / ИНН</th>
|
|
670
|
-
<th>Условия / Скидка</th>
|
|
671
|
-
<th>Статус</th>
|
|
672
|
-
<th>Действия</th>
|
|
673
|
-
</tr></thead>
|
|
674
|
-
<tbody id="admPartnersBody"><tr><td colspan="6" class="muted">Загрузка…</td></tr></tbody>
|
|
675
|
-
</table>
|
|
676
|
-
</div>
|
|
677
|
-
</div>
|
|
678
|
-
|
|
679
|
-
<div class="card">
|
|
680
|
-
<h3 class="h3" style="margin:0 0 12px">Обращения техподдержки (MAX · Telegram · VK)</h3>
|
|
681
|
-
<div class="table-wrap">
|
|
682
|
-
<table class="t">
|
|
683
|
-
<thead><tr>
|
|
684
|
-
<th>Тикет / Канал</th>
|
|
685
|
-
<th>Клиент / Лицензия</th>
|
|
686
|
-
<th>SLA</th>
|
|
687
|
-
<th>Переписка</th>
|
|
688
|
-
<th>Ответ инженера</th>
|
|
689
|
-
</tr></thead>
|
|
690
|
-
<tbody id="admTicketsBody"><tr><td colspan="5" class="muted">Загрузка…</td></tr></tbody>
|
|
691
|
-
</table>
|
|
692
|
-
</div>
|
|
693
|
-
</div>
|
|
694
|
-
</section>
|
|
695
|
-
|
|
696
619
|
<footer>
|
|
697
620
|
<div class="footer">
|
|
698
621
|
<div>
|
|
699
622
|
<div class="brand" style="cursor:default"><img src="/assets/odant-logo.png" alt="" style="width:34px;height:34px"><span class="brand-name">ODANT<b>·</b>WORK</span></div>
|
|
700
|
-
<p style="margin-top:12px">Программно-аппаратный комплекс: встроенная система учёта, документооборот, управление процессами, ИИ-консультант и мультиагентная
|
|
623
|
+
<p style="margin-top:12px">Программно-аппаратный комплекс: встроенная система учёта, документооборот, управление процессами, ИИ-консультант и мультиагентная система. Интегрированные модели — для базовых операций, более мощные ИИ подключаются через API из любого источника.</p>
|
|
701
624
|
</div>
|
|
702
625
|
<div>
|
|
703
626
|
<h4>Комплекс</h4>
|
|
704
627
|
<p>AMD Ryzen™ AI Max+ PRO 495 · Radeon™ 8065S</p>
|
|
705
628
|
<p>192 ГБ LPDDR5x-8533 · SSD 4 ТБ</p>
|
|
706
|
-
<p>От ${rub(P.basePriceRub)} · ${P.baseSeats} вечных
|
|
629
|
+
<p>От ${rub(P.basePriceRub)} · ${P.baseSeats} вечных лицензий + 1 год Enterprise</p>
|
|
707
630
|
</div>
|
|
708
631
|
<div>
|
|
709
632
|
<h4>${esc(VENDOR_CONTACTS.company)}</h4>
|
|
710
633
|
<p>${esc(VENDOR_CONTACTS.address)}</p>
|
|
711
634
|
<p>${VENDOR_CONTACTS.phones.map(esc).join(', ')}</p>
|
|
712
|
-
<p><a href="${esc(VENDOR_CONTACTS.site)}" target="_blank" rel="noopener">${esc(VENDOR_CONTACTS.site.replace(/^https?:\/\//, ''))}</a></p>
|
|
635
|
+
<p><a href="${esc(VENDOR_CONTACTS.site)}" target="_blank" rel="noopener">${esc(VENDOR_CONTACTS.site.replace(/^https?:\/\//, ''))}</a> · <a href="#" data-action="open-oferta">Публичная оферта</a></p>
|
|
713
636
|
</div>
|
|
714
637
|
</div>
|
|
715
638
|
<div class="footer-bottom">
|
|
@@ -719,19 +642,68 @@ export function renderLandingPage({ publicKey = '', regions = null, assetVersion
|
|
|
719
642
|
</footer>
|
|
720
643
|
</div>
|
|
721
644
|
|
|
722
|
-
<!-- Вход в кабинет -->
|
|
645
|
+
<!-- Регистрация / Вход в кабинет и подписание публичной оферты ПЭП -->
|
|
723
646
|
<div class="modal" id="authModal" role="dialog" aria-modal="true" aria-labelledby="authTitle">
|
|
724
|
-
<div class="card">
|
|
647
|
+
<div class="card" style="max-width:540px">
|
|
648
|
+
<div class="modal-head">
|
|
649
|
+
<img src="/assets/odant-logo.png" alt="">
|
|
650
|
+
<div>
|
|
651
|
+
<h3 class="h3" id="authTitle" style="margin:0">Регистрация и подписание оферты</h3>
|
|
652
|
+
<div class="small muted" id="authSub">Заказ комплекса, докупка лицензий и резервирование франшизы доступны после регистрации и акцепта оферты (ПЭП)</div>
|
|
653
|
+
</div>
|
|
654
|
+
</div>
|
|
655
|
+
<div class="row2">
|
|
656
|
+
<div class="field"><label for="authEmail">Корпоративный email *</label><input type="email" id="authEmail" value="admin@maslotorg.ru" required></div>
|
|
657
|
+
<div class="field"><label for="authInn">ИНН организации *</label><input type="text" id="authInn" value="7701234567" inputmode="numeric" required></div>
|
|
658
|
+
</div>
|
|
659
|
+
<div class="row2">
|
|
660
|
+
<div class="field"><label for="authCompany">Наименование организации *</label><input type="text" id="authCompany" value="ООО «Маслоторг»" required></div>
|
|
661
|
+
<div class="field"><label for="authSigner">ФИО и должность подписанта *</label><input type="text" id="authSigner" value="Перепелкин Р.А., Генеральный директор" required></div>
|
|
662
|
+
</div>
|
|
663
|
+
<div class="field"><label for="authLicId">Номер лицензии ПАК (если уже выдан)</label><input type="text" id="authLicId" placeholder="Будет привязан или выпущен автоматически"></div>
|
|
664
|
+
|
|
665
|
+
<div class="oferta-check-box">
|
|
666
|
+
<label class="oferta-check-label">
|
|
667
|
+
<input type="checkbox" id="authOfertaCheck" checked>
|
|
668
|
+
<span>
|
|
669
|
+
Я ознакомился с условиями <a href="#" data-action="open-oferta">Публичного договора-оферты ODANT-WORK (${esc(PUBLIC_OFERTA.version)})</a> и подписываю его простой электронной подписью (ПЭП) от имени указанной организации.
|
|
670
|
+
</span>
|
|
671
|
+
</label>
|
|
672
|
+
</div>
|
|
673
|
+
<div class="status" id="authErrorMsg" style="color:var(--danger);min-height:18px;margin-top:6px"></div>
|
|
674
|
+
<div style="display:flex;gap:10px;margin-top:10px;flex-wrap:wrap">
|
|
675
|
+
<button class="btn btn-primary" style="flex:1" data-action="login">${icon('check')} Зарегистрироваться и подписать оферту</button>
|
|
676
|
+
<button class="btn btn-ghost" id="btnLogoutModal" data-action="logout" style="display:none">Выйти</button>
|
|
677
|
+
<button class="btn btn-ghost" data-action="auth-close">Закрыть</button>
|
|
678
|
+
</div>
|
|
679
|
+
</div>
|
|
680
|
+
</div>
|
|
681
|
+
|
|
682
|
+
<!-- Полный текст Публичного договора-оферты ODANT-WORK -->
|
|
683
|
+
<div class="modal" id="ofertaModal" role="dialog" aria-modal="true" aria-labelledby="ofertaTitle">
|
|
684
|
+
<div class="card" style="max-width:760px">
|
|
725
685
|
<div class="modal-head">
|
|
726
686
|
<img src="/assets/odant-logo.png" alt="">
|
|
727
|
-
<div
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
<div
|
|
733
|
-
|
|
734
|
-
|
|
687
|
+
<div>
|
|
688
|
+
<span class="kicker">Редакция ${esc(PUBLIC_OFERTA.version)} от ${esc(PUBLIC_OFERTA.updatedAt)}</span>
|
|
689
|
+
<h3 class="h3" id="ofertaTitle" style="margin:2px 0 0">${esc(PUBLIC_OFERTA.title)}</h3>
|
|
690
|
+
</div>
|
|
691
|
+
</div>
|
|
692
|
+
<div class="oferta-scroll">
|
|
693
|
+
${PUBLIC_OFERTA.sections.map(s => `
|
|
694
|
+
<div class="oferta-sec">
|
|
695
|
+
<h4>${esc(s.number)}. ${esc(s.title)}</h4>
|
|
696
|
+
<p>${esc(s.text)}</p>
|
|
697
|
+
</div>
|
|
698
|
+
`).join('')}
|
|
699
|
+
<div class="oferta-sec">
|
|
700
|
+
<h4>7. Реквизиты Правообладателя</h4>
|
|
701
|
+
<p><b>${esc(VENDOR_CONTACTS.company)}</b> · Адрес: ${esc(VENDOR_CONTACTS.address)} · Тел.: ${VENDOR_CONTACTS.phones.map(esc).join(', ')} · Сайт: ${esc(VENDOR_CONTACTS.site)}</p>
|
|
702
|
+
</div>
|
|
703
|
+
</div>
|
|
704
|
+
<div style="display:flex;gap:10px;margin-top:14px;justify-content:flex-end;flex-wrap:wrap">
|
|
705
|
+
<button class="btn btn-primary" data-action="accept-from-oferta">${icon('check')} Принять условия и перейти к подписанию ПЭП</button>
|
|
706
|
+
<button class="btn btn-ghost" data-action="oferta-close">Закрыть</button>
|
|
735
707
|
</div>
|
|
736
708
|
</div>
|
|
737
709
|
</div>
|