work-license-server 1.0.7 → 1.0.9
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/assets/landing.js +307 -268
- package/package.json +1 -1
- package/src/landing.js +155 -292
- package/src/server.js +238 -2
- package/src/store.js +109 -15
package/src/landing.js
CHANGED
|
@@ -180,122 +180,41 @@ export function renderLandingPage({ publicKey = '', regions = null, assetVersion
|
|
|
180
180
|
|
|
181
181
|
<nav class="tabs" id="tabs" aria-label="Разделы">
|
|
182
182
|
<span class="tab-ind" id="tabInd"></span>
|
|
183
|
-
<button class="tab active" data-stage="product"
|
|
184
|
-
<button class="tab" data-stage="
|
|
185
|
-
<button class="tab" data-stage="pricing">Тарифы</button>
|
|
186
|
-
<button class="tab" data-stage="order">Комплекс</button>
|
|
187
|
-
<button class="tab" id="tileAddons" data-stage="addons" style="display:none;">Личный кабинет</button>
|
|
183
|
+
<button class="tab active" data-stage="product">О платформе</button>
|
|
184
|
+
<button class="tab" data-stage="clients">Клиентам</button>
|
|
188
185
|
<button class="tab" data-stage="franchise">Франшиза</button>
|
|
189
|
-
<button class="tab" data-stage="
|
|
186
|
+
<button class="tab" id="tileAddons" data-stage="addons" style="display:none;">Личный кабинет</button>
|
|
190
187
|
</nav>
|
|
191
188
|
|
|
192
189
|
<div class="top-actions">
|
|
193
190
|
<button class="icon-btn" id="btnTheme" onclick="toggleTheme()" title="Светлая / тёмная тема" aria-label="Переключить тему">${icon('sun')}</button>
|
|
194
|
-
<button class="btn btn-
|
|
195
|
-
<button class="btn btn-ghost btn-sm" id="btnAuth" data-action="auth">${icon('user')}<span id="btnAuthText">Войти / Регистрация</span></button>
|
|
196
|
-
<button class="btn btn-primary btn-sm" data-stage="order">Заказать</button>
|
|
191
|
+
<button class="btn btn-primary btn-sm" id="btnAuth" data-action="auth">${icon('user')}<span id="btnAuthText">Войти / Регистрация</span></button>
|
|
197
192
|
</div>
|
|
198
193
|
</header>
|
|
199
194
|
|
|
200
|
-
<!-- ============
|
|
195
|
+
<!-- ============ О ПЛАТФОРМЕ (чистое описание без визуального шума) ============ -->
|
|
201
196
|
<section class="stage active" id="stage-product">
|
|
202
|
-
<div class="
|
|
197
|
+
<div class="sec-head" style="margin-top:4px">
|
|
203
198
|
<div>
|
|
204
|
-
<span class="
|
|
205
|
-
<h1 class="
|
|
206
|
-
<p class="lead">ODANT-WORK — вычислительный центр предприятия, который ставится в серверную и работает автономно. Встроенная система учёта, единое пространство документов и задач, ИИ-консультант в каждой форме и команда ИИ-агентов — без облаков и передачи данных наружу.</p>
|
|
207
|
-
<div class="hero-cta">
|
|
208
|
-
<button class="btn btn-primary btn-lg" data-stage="order">Заказать комплекс · ${rub(P.basePriceRub)}</button>
|
|
209
|
-
<button class="btn btn-ghost btn-lg" data-stage="agents">${icon('agents')} Как работают ИИ-агенты</button>
|
|
210
|
-
</div>
|
|
211
|
-
<div class="trust">
|
|
212
|
-
<span>${icon('shield')} Данные не покидают контур</span>
|
|
213
|
-
<span>${icon('key')} ${P.baseSeats} вечных лицензий</span>
|
|
214
|
-
<span>${icon('check')} 1 год поддержки Enterprise (далее — по желанию)</span>
|
|
215
|
-
</div>
|
|
216
|
-
</div>
|
|
217
|
-
<div class="showcase" aria-hidden="true">
|
|
218
|
-
<div class="showcase-ring"></div>
|
|
219
|
-
<div class="showcase-ring r2"></div>
|
|
220
|
-
<div class="showcase-logo"><img src="/assets/odant-logo.png" alt=""></div>
|
|
221
|
-
<div class="chipf c1"><b>132 TOPS</b>ИИ-производительность</div>
|
|
222
|
-
<div class="chipf c2"><b>192 ГБ</b>единой памяти LPDDR5x</div>
|
|
223
|
-
<div class="chipf c3"><b>16 / 32</b>ядра / потока Zen 5</div>
|
|
224
|
-
<div class="chipf c4"><b>4 ТБ</b>NVMe PCIe® 4.0</div>
|
|
199
|
+
<span class="kicker">Платформа цифровой организации</span>
|
|
200
|
+
<h1 class="h2" style="font-size:clamp(1.9rem,3vw,2.6rem);margin:4px 0 0">ODANT-WORK — учёт, документооборот, процессы и <span class="grad">приватный ИИ</span></h1>
|
|
225
201
|
</div>
|
|
202
|
+
<p>Все данные предприятия — справочники, проводки, документы, переписка и задачи — живут в единой модели с общими правами доступа и работают автономно в вашем контуре без передачи данных наружу.</p>
|
|
226
203
|
</div>
|
|
227
204
|
|
|
228
|
-
<div class="kpis reveal">
|
|
229
|
-
<div class="kpi"><b data-count="132">132<small>TOPS</small></b><span>общая ИИ-производительность, NPU 55 TOPS</span></div>
|
|
230
|
-
<div class="kpi"><b data-count="61">61<small>TFLOPS</small></b><span>FP16 на графике Radeon™ 8065S</span></div>
|
|
231
|
-
<div class="kpi"><b data-count="192">192<small>ГБ</small></b><span>единая память для моделей и данных</span></div>
|
|
232
|
-
<div class="kpi"><b data-count="5.2" data-dec="1">5.2<small>ГГц</small></b><span>максимальная частота, 80 МБ кэша</span></div>
|
|
233
|
-
</div>
|
|
234
|
-
|
|
235
|
-
<div class="sec-head reveal">
|
|
236
|
-
<div>
|
|
237
|
-
<span class="kicker">Что внутри</span>
|
|
238
|
-
<h2 class="h2">Одна система вместо зоопарка программ</h2>
|
|
239
|
-
</div>
|
|
240
|
-
<p>Все данные предприятия — справочники, проводки, документы, переписка и задачи — живут в одной модели с едиными правами доступа. Поэтому ИИ видит полную картину и действует по правилам вашей организации.</p>
|
|
241
|
-
</div>
|
|
242
205
|
<div class="bento">
|
|
243
206
|
<article class="card spot reveal wide"><div class="ico">${icon('ledger')}</div><h3 class="h3">Встроенная система учёта</h3><p class="note">План счетов, справочники и аналитики, явная двойная запись с исправлением только через сторно. Оборотно-сальдовая ведомость, анализ, обороты и журнал проводок — в едином табличном стандарте.</p></article>
|
|
244
|
-
<article class="card spot reveal wide"><div class="ico">${icon('docs')}</div><h3 class="h3"
|
|
245
|
-
<article class="card spot reveal"><div class="ico">${icon('flow')}</div><h3 class="h3">Управление процессами</h3><p class="note">Структура подразделений,
|
|
207
|
+
<article class="card spot reveal wide"><div class="ico">${icon('docs')}</div><h3 class="h3">Документооборот и офис</h3><p class="note">Единое файловое пространство подразделений, первичные документы по шаблонам, согласования, версии и восстановление файлов. Таблицы, тексты и презентации редактируются прямо в системе.</p></article>
|
|
208
|
+
<article class="card spot reveal"><div class="ico">${icon('flow')}</div><h3 class="h3">Управление процессами</h3><p class="note">Структура подразделений, роли BOSS и USER, рабочие места, поручения со сроками и журнал всех фактов.</p></article>
|
|
246
209
|
<article class="card spot reveal"><div class="ico">${icon('ai')}</div><h3 class="h3">ИИ-консультант</h3><p class="note">Кнопка «?» в любой форме и голосовой диалог: объяснит, найдёт, посчитает и проведёт операцию.</p></article>
|
|
247
210
|
<article class="card spot reveal"><div class="ico">${icon('agents')}</div><h3 class="h3">Мультиагентная система</h3><p class="note">${AI_PLATFORM.agents.length} ролевых ИИ-агентов и ${AI_PLATFORM.skillsCount}+ навыков работают параллельно и строго в рамках прав.</p></article>
|
|
248
211
|
</div>
|
|
249
212
|
|
|
250
|
-
<div class="
|
|
251
|
-
<div class="spec-wrap">
|
|
252
|
-
<div>
|
|
253
|
-
<span class="kicker">Паспорт комплекса</span>
|
|
254
|
-
<h2 class="h2">ODANT-WORK · ${esc(P.sku)}</h2>
|
|
255
|
-
<div class="price-big">${rub(P.basePriceRub)}</div>
|
|
256
|
-
<p class="note">Вечная лицензия на ${P.baseSeats} одновременных рабочих сессий, привязанная к оборудованию, и ${P.includedSupportYears} год максимальной поддержки уровня Enterprise (24/7, реакция ≤ 15 мин) — в комплекте. Дальнейшее продление поддержки и докупка мест — по желанию.</p>
|
|
257
|
-
<div class="hero-cta" style="margin-top:20px">
|
|
258
|
-
<button class="btn btn-primary" data-stage="order">Оформить заказ</button>
|
|
259
|
-
<button class="btn btn-ghost" data-stage="pricing">Тарифы поддержки</button>
|
|
260
|
-
</div>
|
|
261
|
-
</div>
|
|
262
|
-
<dl class="spec">
|
|
263
|
-
<div><dt>Процессор</dt><dd>${esc(H.cpu)}</dd></div>
|
|
264
|
-
<div><dt>Графика</dt><dd>${esc(H.gpu)}</dd></div>
|
|
265
|
-
<div><dt>ИИ-ускорение</dt><dd>${esc(H.aiEngine)}</dd></div>
|
|
266
|
-
<div><dt>Память</dt><dd>${esc(H.ram)}</dd></div>
|
|
267
|
-
<div><dt>Накопитель</dt><dd>${esc(H.storage)}</dd></div>
|
|
268
|
-
<div><dt>Защита</dt><dd>${esc(H.security)}</dd></div>
|
|
269
|
-
<div><dt>Лицензия</dt><dd>По одновременным сессиям, привязка к HWID и ключу узла</dd></div>
|
|
270
|
-
</dl>
|
|
271
|
-
</div>
|
|
272
|
-
</div>
|
|
273
|
-
|
|
274
|
-
<div class="sec-head reveal">
|
|
275
|
-
<div>
|
|
276
|
-
<span class="kicker">Приватный и гибридный ИИ</span>
|
|
277
|
-
<h2 class="h2">Четыре типа базовых моделей уже установлены</h2>
|
|
278
|
-
</div>
|
|
279
|
-
<p>Интегрированные локальные модели предназначены для базовых ежедневных операций внутри контура. Если требуются более мощные модели ИИ, их можно подключить через API из любого источника.</p>
|
|
280
|
-
</div>
|
|
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">
|
|
213
|
+
<div class="agents-hero" style="margin-top:12px">
|
|
283
214
|
<div>
|
|
284
|
-
<span class="kicker"
|
|
285
|
-
<
|
|
286
|
-
<p class="
|
|
287
|
-
</div>
|
|
288
|
-
<button class="btn btn-ghost btn-sm" data-stage="agents">Подробнее об ИИ-агентах →</button>
|
|
289
|
-
</div>
|
|
290
|
-
</section>
|
|
291
|
-
|
|
292
|
-
<!-- ============ ИИ-АГЕНТЫ ============ -->
|
|
293
|
-
<section class="stage" id="stage-agents">
|
|
294
|
-
<div class="agents-hero">
|
|
295
|
-
<div>
|
|
296
|
-
<span class="kicker">ИИ-консультант</span>
|
|
297
|
-
<h2 class="h2" style="font-size:clamp(2rem,3.6vw,3.2rem)">Помощник, который <span class="grad">знает вашу организацию</span></h2>
|
|
298
|
-
<p class="lead">Консультант встроен в каждую форму системы. Он видит открытый документ, понимает структуру учёта и права пользователя — и не просто отвечает, а выполняет работу.</p>
|
|
215
|
+
<span class="kicker">ИИ-консультант в каждой форме</span>
|
|
216
|
+
<h2 class="h2">Помощник, который <span class="grad">знает вашу организацию</span></h2>
|
|
217
|
+
<p class="lead">Консультант видит открытый документ, понимает структуру учёта и права пользователя — и не просто отвечает на вопросы, а выполняет работу.</p>
|
|
299
218
|
<ul class="list">${AI_PLATFORM.consultant.features.map(f => `<li>${esc(f)}</li>`).join('')}</ul>
|
|
300
219
|
</div>
|
|
301
220
|
<div class="mock" id="consultantMock">
|
|
@@ -324,95 +243,122 @@ export function renderLandingPage({ publicKey = '', regions = null, assetVersion
|
|
|
324
243
|
</div>
|
|
325
244
|
</div>
|
|
326
245
|
|
|
327
|
-
<div class="sec-head reveal">
|
|
328
|
-
<div><span class="kicker">Оркестрация</span><h2 class="h2">Как агенты работают вместе</h2></div>
|
|
329
|
-
<p>Параллельность и скорость — без потери контроля: права, подтверждения и журнал действий заложены в код платформы, а не в текст подсказки.</p>
|
|
330
|
-
</div>
|
|
331
246
|
<div class="grid g3">${renderOrchestration()}</div>
|
|
332
247
|
|
|
333
|
-
<div class="
|
|
334
|
-
<div class="sec-head" style="margin-bottom:18px">
|
|
335
|
-
<div><span class="kicker">Навыки</span><h2 class="h2">${AI_PLATFORM.skillsCount}+ проверенных рецептов работы</h2></div>
|
|
336
|
-
<p>Навык — описанный порядок решения типовой задачи. Удачный результат агента с одобрения сотрудника сохраняется как новый навык подразделения.</p>
|
|
337
|
-
</div>
|
|
338
|
-
<div class="skills">${AI_PLATFORM.skills.map(s => `<span>${esc(s)}</span>`).join('')}</div>
|
|
339
|
-
</div>
|
|
340
|
-
</section>
|
|
341
|
-
|
|
342
|
-
<!-- ============ ТАРИФЫ ============ -->
|
|
343
|
-
<section class="stage" id="stage-pricing">
|
|
344
|
-
<div class="sec-head">
|
|
248
|
+
<div class="sec-head reveal">
|
|
345
249
|
<div>
|
|
346
|
-
<span class="kicker"
|
|
347
|
-
<h2 class="h2"
|
|
250
|
+
<span class="kicker">Приватный и гибридный ИИ</span>
|
|
251
|
+
<h2 class="h2">Четыре типа базовых моделей уже установлены</h2>
|
|
348
252
|
</div>
|
|
349
|
-
<p
|
|
253
|
+
<p>Интегрированные локальные модели предназначены для базовых ежедневных операций внутри контура. Если требуются более мощные модели ИИ, их можно подключить через API из любого источника.</p>
|
|
350
254
|
</div>
|
|
351
|
-
<div class="
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
<
|
|
255
|
+
<div class="grid g4">${renderModels()}</div>
|
|
256
|
+
|
|
257
|
+
<div class="card card-glow reveal">
|
|
258
|
+
<div class="spec-wrap">
|
|
259
|
+
<div>
|
|
260
|
+
<span class="kicker">Аппаратное исполнение или собственная инфраструктура</span>
|
|
261
|
+
<h2 class="h2">ODANT-WORK · ${esc(P.sku)}</h2>
|
|
262
|
+
<div class="price-big">${rub(P.basePriceRub)}</div>
|
|
263
|
+
<p class="note">Вечная лицензия на ${P.baseSeats} одновременных рабочих сессий и ${P.includedSupportYears} год поддержки уровня Enterprise — в комплекте с сервером (или ${rub(P.baseLicensePriceRub || 4_000_000)} за базовую лицензию без оборудования при установке через <code>npm</code>).</p>
|
|
264
|
+
<div class="hero-cta" style="margin-top:20px">
|
|
265
|
+
<button class="btn btn-primary" data-stage="clients">Перейти к покупке →</button>
|
|
266
|
+
<button class="btn btn-ghost" data-stage="franchise">Региональная франшиза</button>
|
|
267
|
+
</div>
|
|
268
|
+
</div>
|
|
269
|
+
<dl class="spec">
|
|
270
|
+
<div><dt>Процессор</dt><dd>${esc(H.cpu)}</dd></div>
|
|
271
|
+
<div><dt>Графика</dt><dd>${esc(H.gpu)}</dd></div>
|
|
272
|
+
<div><dt>ИИ-ускорение</dt><dd>${esc(H.aiEngine)}</dd></div>
|
|
273
|
+
<div><dt>Память</dt><dd>${esc(H.ram)}</dd></div>
|
|
274
|
+
<div><dt>Накопитель</dt><dd>${esc(H.storage)}</dd></div>
|
|
275
|
+
<div><dt>Защита</dt><dd>${esc(H.security)}</dd></div>
|
|
276
|
+
<div><dt>Лицензия</dt><dd>По одновременным сессиям, файлы .lic.json в #system</dd></div>
|
|
277
|
+
</dl>
|
|
356
278
|
</div>
|
|
357
|
-
${renderLadder('ladderPricing')}
|
|
358
279
|
</div>
|
|
359
280
|
</section>
|
|
360
281
|
|
|
361
|
-
<!-- ============
|
|
362
|
-
<section class="stage" id="stage-
|
|
363
|
-
<div class="sec-head">
|
|
364
|
-
<div><span class="kicker">Заказ</span><h2 class="h2">Программно-аппаратный комплекс ODANT-WORK</h2></div>
|
|
365
|
-
<p>Сервер AMD Ryzen™ AI Max+ PRO 495 · 192 ГБ · 4 ТБ с установленной платформой, вечной лицензией на ${P.baseSeats} мест и 1 годом поддержки Enterprise (дальше — по желанию). Оплата через ЮKassa с чеком по 54-ФЗ.</p>
|
|
366
|
-
</div>
|
|
367
|
-
<div class="card oferta-banner" data-oferta-banner></div>
|
|
282
|
+
<!-- ============ КЛИЕНТАМ: СРАЗУ КАЛЬКУЛЯТОР СВЕРХУ ============ -->
|
|
283
|
+
<section class="stage" id="stage-clients">
|
|
368
284
|
<div class="split">
|
|
369
285
|
<div class="card">
|
|
370
286
|
<div class="field">
|
|
371
|
-
<label
|
|
287
|
+
<label>1. Базовая постоянная лицензия (10 вечных пользователей + ИИ-агенты)</label>
|
|
372
288
|
<div class="seg" id="segPakVariant">
|
|
373
|
-
<button data-variant="pak" class="on"
|
|
374
|
-
<button data-variant="license_only"
|
|
289
|
+
<button data-variant="pak" class="on">С машинкой (ПАК)<small>${rub(P.basePriceRub)} · сервер + 10 вечных мест</small></button>
|
|
290
|
+
<button data-variant="license_only">Без машинки (лицензия)<small>${rub(P.baseLicensePriceRub || 4_000_000)} · 10 вечных мест</small></button>
|
|
291
|
+
<button data-variant="addons_only">Только доп. юзеры<small>0 ₽ · базовая уже есть</small></button>
|
|
375
292
|
</div>
|
|
376
293
|
</div>
|
|
377
|
-
<div class="row2">
|
|
378
|
-
<div class="field"><label for="inpPakOrg">Организация</label><input type="text" id="inpPakOrg" value="ООО «Маслоторг»"></div>
|
|
379
|
-
<div class="field"><label for="inpPakInn">ИНН</label><input type="text" id="inpPakInn" value="7701234567" inputmode="numeric"></div>
|
|
380
|
-
</div>
|
|
381
|
-
<div class="field"><label for="inpPakEmail">Email для счёта и личного кабинета</label><input type="email" id="inpPakEmail" value="admin@maslotorg.ru"></div>
|
|
382
294
|
<div class="field">
|
|
383
|
-
<label
|
|
384
|
-
<
|
|
295
|
+
<label>2. Дополнительные временные пользователи (сверх 10 вечных)</label>
|
|
296
|
+
<div style="display:flex;align-items:center;gap:16px">
|
|
297
|
+
<input type="range" id="inpPakExtraSeats" min="0" max="150" value="0" style="flex:1">
|
|
298
|
+
<input type="number" id="inpPakExtraSeatsNum" min="0" max="2000" value="0" style="width:110px">
|
|
299
|
+
</div>
|
|
385
300
|
</div>
|
|
386
|
-
<div class="
|
|
387
|
-
<
|
|
388
|
-
|
|
301
|
+
<div class="row2">
|
|
302
|
+
<div class="field">
|
|
303
|
+
<label>Уровень поддержки доп. мест</label>
|
|
304
|
+
<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>
|
|
305
|
+
</div>
|
|
306
|
+
<div class="field">
|
|
307
|
+
<label for="inpPakYears">Срок временных мест, лет (1–5)</label>
|
|
308
|
+
<input type="number" id="inpPakYears" min="1" max="5" value="1">
|
|
309
|
+
</div>
|
|
389
310
|
</div>
|
|
390
|
-
<
|
|
311
|
+
<div class="field" style="margin-top:6px"><label>Скидка от количества дополнительных мест</label>${renderLadder('ladderPricing')}</div>
|
|
391
312
|
</div>
|
|
313
|
+
|
|
392
314
|
<div class="card summary card-glow">
|
|
393
|
-
<span class="kicker"
|
|
315
|
+
<span class="kicker">Ваш выбор</span>
|
|
394
316
|
<div class="sum-total" id="lblPakTotal">${rub(P.basePriceRub)}</div>
|
|
317
|
+
<div class="small" id="lblPakDiscount" style="color:var(--ok);font-weight:650">Включает 10 вечных мест и 1 год поддержки Enterprise</div>
|
|
395
318
|
<div class="sum-lines" id="lblPakBreakdown"></div>
|
|
396
|
-
<button class="btn btn-primary btn-lg" style="width:100%" data-action="
|
|
397
|
-
<
|
|
319
|
+
<button class="btn btn-primary btn-lg" style="width:100%" data-action="buy-client-config">Купить</button>
|
|
320
|
+
<p class="small muted" style="margin:8px 0 0;text-align:center">При нажатии «Купить» заказ добавится в ваш Личный кабинет, где вы сможете оплатить его через ЮKassa или выставить счёт-договор для юр. лица.</p>
|
|
398
321
|
<div class="status" id="pakOrderStatus"></div>
|
|
399
322
|
</div>
|
|
400
323
|
</div>
|
|
324
|
+
|
|
325
|
+
<div class="sec-head" style="margin-top:16px">
|
|
326
|
+
<div>
|
|
327
|
+
<span class="kicker">Тарифы поддержки и конкурентных мест</span>
|
|
328
|
+
<h2 class="h2">Условия лицензирования и SLA</h2>
|
|
329
|
+
</div>
|
|
330
|
+
<p>Сразу после установки из <code>npm</code> система работает бесплатно в режиме настройки (1 сессия BOSS, ИИ-агенты отключены). Базовая постоянная лицензия открывает <b>${P.baseSeats} вечных одновременных сессий</b> и включает агентскую ИИ-систему.</p>
|
|
331
|
+
</div>
|
|
332
|
+
<div class="tiers">${renderTiers()}</div>
|
|
401
333
|
</section>
|
|
402
334
|
|
|
403
|
-
<!-- ============
|
|
335
|
+
<!-- ============ ЛИЧНЫЙ КАБИНЕТ (открывается после входа / регистрации) ============ -->
|
|
404
336
|
<section class="stage" id="stage-addons">
|
|
405
337
|
<div class="sec-head">
|
|
406
|
-
<div><span class="kicker">Личный кабинет владельца</span><h2 class="h2"
|
|
338
|
+
<div><span class="kicker">Личный кабинет владельца</span><h2 class="h2">Заказы, токен привязки и лицензии</h2></div>
|
|
407
339
|
<p id="userBadgeBox"></p>
|
|
408
340
|
</div>
|
|
409
|
-
<div class="card oferta-banner" data-oferta-banner></div>
|
|
410
341
|
|
|
411
|
-
<div class="
|
|
342
|
+
<div class="card" style="margin-bottom:20px">
|
|
343
|
+
<div style="display:flex;justify-content:space-between;align-items:center;gap:12px;flex-wrap:wrap">
|
|
344
|
+
<div>
|
|
345
|
+
<span class="kicker">Заказы и оплата</span>
|
|
346
|
+
<h3 class="h3" style="margin:4px 0 0">Ваши заказы в Личном кабинете</h3>
|
|
347
|
+
</div>
|
|
348
|
+
<div style="display:flex;gap:8px;flex-wrap:wrap">
|
|
349
|
+
<button class="btn btn-ghost btn-sm" data-stage="clients">+ Добавить лицензию / ПАК</button>
|
|
350
|
+
<button class="btn btn-ghost btn-sm" data-stage="franchise">+ Зарезервировать франшизу</button>
|
|
351
|
+
<button class="btn btn-ghost btn-sm" data-action="refresh-cabinet">Обновить</button>
|
|
352
|
+
</div>
|
|
353
|
+
</div>
|
|
354
|
+
<div id="cabinetOrdersBox" style="margin-top:14px"></div>
|
|
355
|
+
</div>
|
|
356
|
+
|
|
357
|
+
<div class="split">
|
|
412
358
|
<div class="card">
|
|
413
|
-
<span class="kicker"
|
|
359
|
+
<span class="kicker">Привязка локального сервера WORK</span>
|
|
414
360
|
<h3 class="h3" style="margin:4px 0 8px">Токен владельца (содержит URL сервера поддержки)</h3>
|
|
415
|
-
<p class="small" style="margin:0 0 12px">Скопируйте этот токен и вставьте его в разделе <b>WORK → Лицензия</b> вашей локальной системы. По этому токену система
|
|
361
|
+
<p class="small" style="margin:0 0 12px">Скопируйте этот токен и вставьте его в разделе <b>WORK → Лицензия</b> вашей локальной системы. По этому токену система сама скачивает и обновляет оплаченные файлы лицензий в папку <code>#system</code>.</p>
|
|
416
362
|
<div style="display:flex;gap:10px;flex-wrap:wrap;align-items:center">
|
|
417
363
|
<input type="text" id="inpCabinetHubToken" readonly placeholder="owk1..." style="flex:1;min-width:220px;font-family:monospace">
|
|
418
364
|
<button class="btn btn-primary btn-sm" data-action="copy-hub-token">Скопировать токен</button>
|
|
@@ -422,72 +368,15 @@ export function renderLandingPage({ publicKey = '', regions = null, assetVersion
|
|
|
422
368
|
</div>
|
|
423
369
|
|
|
424
370
|
<div class="card">
|
|
425
|
-
<
|
|
426
|
-
|
|
427
|
-
<span class="kicker">Шаг 2 · Ваши выпущенные лицензии</span>
|
|
428
|
-
<h3 class="h3" style="margin:4px 0 6px">Файлы лицензий в личном кабинете</h3>
|
|
429
|
-
</div>
|
|
430
|
-
<button class="btn btn-ghost btn-sm" data-action="refresh-cabinet">Обновить</button>
|
|
431
|
-
</div>
|
|
371
|
+
<span class="kicker">Действующие лицензии (.lic.json) и франшизы</span>
|
|
372
|
+
<h3 class="h3" style="margin:4px 0 6px">Выпущенные файлы лицензий</h3>
|
|
432
373
|
<div id="cabinetLicensesBox" class="small" style="margin-top:8px;line-height:1.55"></div>
|
|
433
374
|
</div>
|
|
434
375
|
</div>
|
|
435
|
-
|
|
436
|
-
<div class="split">
|
|
437
|
-
<div class="card">
|
|
438
|
-
<span class="kicker">Шаг 3 · Приобретение базовой и дополнительных лицензий</span>
|
|
439
|
-
<div class="field" style="margin-top:8px">
|
|
440
|
-
<label>Базовая постоянная лицензия (10 вечных пользователей + включение ИИ-агентов)</label>
|
|
441
|
-
<div class="seg" id="segCabinetBase">
|
|
442
|
-
<button data-base="license_only" class="on">Базовая лицензия (без железа)<small>${rub(P.baseLicensePriceRub || 4_000_000)} · 10 вечных мест</small></button>
|
|
443
|
-
<button data-base="pak">Комплект с машиной<small>${rub(P.basePriceRub)} · сервер + 10 мест</small></button>
|
|
444
|
-
<button data-base="none">Только доп. временные<small>0 ₽ · базовая уже куплена</small></button>
|
|
445
|
-
</div>
|
|
446
|
-
</div>
|
|
447
|
-
<div class="field">
|
|
448
|
-
<label>Дополнительные временные места (сверх 10 вечных)</label>
|
|
449
|
-
<div style="display:flex;align-items:center;gap:16px">
|
|
450
|
-
<input type="range" id="rngAddonSeats" min="0" max="150" value="0" style="flex:1">
|
|
451
|
-
<input type="number" id="inpSeats" min="0" max="2000" value="0" style="width:110px">
|
|
452
|
-
</div>
|
|
453
|
-
</div>
|
|
454
|
-
<div class="field">
|
|
455
|
-
<label>Уровень поддержки дополнительных мест</label>
|
|
456
|
-
<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>
|
|
457
|
-
</div>
|
|
458
|
-
<div class="row2">
|
|
459
|
-
<div class="field"><label for="inpYears">Срок временных лицензий, лет (кратно годам)</label><input type="number" id="inpYears" min="1" max="5" value="1"></div>
|
|
460
|
-
<div class="field"><label for="inpLicId">Идентификатор лицензии</label><input type="text" id="inpLicId" readonly></div>
|
|
461
|
-
</div>
|
|
462
|
-
<div class="field" style="margin-top:6px"><label>Скидка от количества доп. мест</label>${renderLadder('ladderAddons')}</div>
|
|
463
|
-
</div>
|
|
464
|
-
<div class="card summary card-glow">
|
|
465
|
-
<span class="kicker">К оплате</span>
|
|
466
|
-
<div class="sum-total" id="lblTotal">0 ₽</div>
|
|
467
|
-
<div class="small" id="lblDiscountBadge" style="color:var(--ok);font-weight:650"></div>
|
|
468
|
-
<div class="sum-lines" id="lblBreakdown"></div>
|
|
469
|
-
<button class="btn btn-primary btn-lg" style="width:100%" data-action="order-addons">Оплатить через ЮKassa</button>
|
|
470
|
-
<button class="btn btn-ghost btn-sm" style="width:100%;margin-top:8px" data-action="order-addons-invoice">Выставить счёт-договор (для юр. лиц)</button>
|
|
471
|
-
<div class="status" id="orderStatus"></div>
|
|
472
|
-
</div>
|
|
473
|
-
</div>
|
|
474
376
|
</section>
|
|
475
377
|
|
|
476
|
-
<!-- ============
|
|
378
|
+
<!-- ============ ФРАНШИЗА: СРАЗУ КАРТА СВЕРХУ, ВСЯ ПРОЧАЯ ИНФОРМАЦИЯ ВНИЗУ ============ -->
|
|
477
379
|
<section class="stage" id="stage-franchise">
|
|
478
|
-
<div class="sec-head">
|
|
479
|
-
<div><span class="kicker">Партнёрская программа</span><h2 class="h2">Региональная франшиза ODANT-WORK</h2></div>
|
|
480
|
-
<p>Число франшиз в субъекте пропорционально населению, паушальный взнос — экономике региона. Резерв закрепляется сразу после невозвратного залога ${rub(FRANCHISE_PROGRAM.reservationDepositRub)}, полная оплата паушального взноса — в течение 1 года.</p>
|
|
481
|
-
</div>
|
|
482
|
-
<div class="card oferta-banner" data-oferta-banner></div>
|
|
483
|
-
<div class="stats">
|
|
484
|
-
<div class="stat"><b id="statVacant">${totalVacant}</b><span>вакантных франшиз</span></div>
|
|
485
|
-
<div class="stat"><b>${visibleRegions.length}</b><span>субъектов РФ</span></div>
|
|
486
|
-
<div class="stat"><b>${rub(FRANCHISE_PROGRAM.baseFranchiseFeeRub)}</b><span>базовый паушальный взнос</span></div>
|
|
487
|
-
<div class="stat"><b>${rub(FRANCHISE_PROGRAM.reservationDepositRub)}</b><span>залог за резерв</span></div>
|
|
488
|
-
<div class="stat"><b>${FRANCHISE_PROGRAM.minDiscountPercent}→${FRANCHISE_PROGRAM.maxDiscountPercent}%</b><span>скидка партнёра от объёма</span></div>
|
|
489
|
-
</div>
|
|
490
|
-
|
|
491
380
|
<div class="map-layout">
|
|
492
381
|
<div class="card map-card">
|
|
493
382
|
<div class="map-tools">
|
|
@@ -534,16 +423,25 @@ export function renderLandingPage({ publicKey = '', regions = null, assetVersion
|
|
|
534
423
|
<div><span>Индекс экономики</span><b id="mapRegIndex">—</b></div>
|
|
535
424
|
<div><span>Остаток (в течение года)</span><b id="mapRegRest">—</b></div>
|
|
536
425
|
</div>
|
|
537
|
-
<
|
|
538
|
-
<
|
|
539
|
-
<div class="field"><label for="inpPartnerInn">ИНН</label><input type="text" id="inpPartnerInn" value="6670123456" inputmode="numeric"></div>
|
|
540
|
-
<div class="field"><label for="inpPartnerEmail">Email</label><input type="email" id="inpPartnerEmail" value="partner@uraltech.ru"></div>
|
|
541
|
-
</div>
|
|
542
|
-
<button class="btn btn-primary" style="width:100%" id="btnReserveSelected" data-action="reserve-selected" disabled>Зарезервировать · залог ${rub(FRANCHISE_PROGRAM.reservationDepositRub)}</button>
|
|
426
|
+
<button class="btn btn-primary" style="width:100%;margin-top:8px" id="btnReserveSelected" data-action="reserve-selected" disabled>Зарезервировать · залог ${rub(FRANCHISE_PROGRAM.reservationDepositRub)}</button>
|
|
427
|
+
<p class="small muted" style="margin:8px 0 0;text-align:center">При нажатии «Зарезервировать» заявка на регион добавится как заказ в ваш Личный кабинет.</p>
|
|
543
428
|
<div class="status" id="partnerActionMsg"></div>
|
|
544
429
|
</aside>
|
|
545
430
|
</div>
|
|
546
431
|
|
|
432
|
+
<div class="sec-head" style="margin-top:8px">
|
|
433
|
+
<div><span class="kicker">Партнёрская программа</span><h2 class="h2">Региональная франшиза ODANT-WORK</h2></div>
|
|
434
|
+
<p>Число франшиз в субъекте пропорционально населению, паушальный взнос — экономике региона. Резерв закрепляется сразу после невозвратного залога ${rub(FRANCHISE_PROGRAM.reservationDepositRub)}, полная оплата паушального взноса — в течение 1 года.</p>
|
|
435
|
+
</div>
|
|
436
|
+
|
|
437
|
+
<div class="stats">
|
|
438
|
+
<div class="stat"><b id="statVacant">${totalVacant}</b><span>вакантных франшиз</span></div>
|
|
439
|
+
<div class="stat"><b>${visibleRegions.length}</b><span>субъектов РФ</span></div>
|
|
440
|
+
<div class="stat"><b>${rub(FRANCHISE_PROGRAM.baseFranchiseFeeRub)}</b><span>базовый паушальный взнос</span></div>
|
|
441
|
+
<div class="stat"><b>${rub(FRANCHISE_PROGRAM.reservationDepositRub)}</b><span>залог за резерв</span></div>
|
|
442
|
+
<div class="stat"><b>${FRANCHISE_PROGRAM.minDiscountPercent}→${FRANCHISE_PROGRAM.maxDiscountPercent}%</b><span>скидка партнёра от объёма</span></div>
|
|
443
|
+
</div>
|
|
444
|
+
|
|
547
445
|
<div class="card">
|
|
548
446
|
<div class="map-tools">
|
|
549
447
|
<h3 class="h3" style="margin:0">Все субъекты Российской Федерации</h3>
|
|
@@ -592,56 +490,6 @@ export function renderLandingPage({ publicKey = '', regions = null, assetVersion
|
|
|
592
490
|
<div class="grid g4">${renderTracks()}</div>
|
|
593
491
|
</section>
|
|
594
492
|
|
|
595
|
-
<!-- ============ ПОДДЕРЖКА ============ -->
|
|
596
|
-
<section class="stage" id="stage-support">
|
|
597
|
-
<div class="sec-head">
|
|
598
|
-
<div><span class="kicker">Сервис</span><h2 class="h2">Поддержка в мессенджерах MAX, Telegram и VK</h2></div>
|
|
599
|
-
<p>Боты принимают обращения, показывают статус лицензии, выставляют счета и передают вопросы инженеру по SLA вашего тарифа.</p>
|
|
600
|
-
</div>
|
|
601
|
-
<div class="grid g2">
|
|
602
|
-
<div class="card">
|
|
603
|
-
<h3 class="h3">Консоль бота</h3>
|
|
604
|
-
<div class="row2" style="margin-top:12px">
|
|
605
|
-
<div class="field"><label for="botChannel">Канал</label><select id="botChannel"><option value="max">MAX</option><option value="telegram">Telegram</option><option value="vk">VK</option></select></div>
|
|
606
|
-
<div class="field"><label for="botChatId">Chat ID</label><input type="text" id="botChatId" value="client-101"></div>
|
|
607
|
-
</div>
|
|
608
|
-
<div class="field"><label for="botText">Команда или текст</label>
|
|
609
|
-
<div style="display:flex;gap:8px"><input type="text" id="botText" value="/start"><button class="btn btn-primary" data-action="bot-send">${icon('send')}</button></div>
|
|
610
|
-
</div>
|
|
611
|
-
<div class="chips" style="margin-bottom:12px">
|
|
612
|
-
<button class="chip" data-bot="/status">/status</button>
|
|
613
|
-
<button class="chip" data-bot="/buy business 10">/buy business 10</button>
|
|
614
|
-
<button class="chip" data-bot="/help">/help</button>
|
|
615
|
-
</div>
|
|
616
|
-
<div class="console" id="botReplyBox">Ответ бота появится здесь…</div>
|
|
617
|
-
</div>
|
|
618
|
-
<div class="card">
|
|
619
|
-
<div style="display:flex;justify-content:space-between;align-items:center;gap:10px;flex-wrap:wrap">
|
|
620
|
-
<h3 class="h3" style="margin:0">Ваша лицензия и привязка мессенджеров</h3>
|
|
621
|
-
<div style="display:flex;gap:8px;flex-wrap:wrap">
|
|
622
|
-
<button class="btn btn-ghost btn-sm" data-action="auth">Личный кабинет</button>
|
|
623
|
-
<button class="btn btn-ghost btn-sm" data-action="open-oferta">Договор-оферта</button>
|
|
624
|
-
</div>
|
|
625
|
-
</div>
|
|
626
|
-
<div class="console" id="clientLicenseBox" style="margin-top:14px">Войдите в личный кабинет и подпишите договор-оферту, чтобы получить код привязки вашего комплекса к ботам MAX, Telegram и VK.</div>
|
|
627
|
-
</div>
|
|
628
|
-
</div>
|
|
629
|
-
<div class="card">
|
|
630
|
-
<div class="spec-wrap">
|
|
631
|
-
<div>
|
|
632
|
-
<span class="kicker">Разработчик платформы</span>
|
|
633
|
-
<h2 class="h2">${esc(VENDOR_CONTACTS.company)}</h2>
|
|
634
|
-
<p class="note">${esc(VENDOR_CONTACTS.description)}. Головной офис ODANT — в Рязани.</p>
|
|
635
|
-
</div>
|
|
636
|
-
<div>
|
|
637
|
-
<div class="contact-row">${icon('pin')}<div><b>${esc(VENDOR_CONTACTS.address)}</b><br><a href="https://yandex.ru/maps/?pt=${VENDOR_CONTACTS.geo.lon},${VENDOR_CONTACTS.geo.lat}&z=17&l=map" target="_blank" rel="noopener">Открыть на карте</a></div></div>
|
|
638
|
-
<div class="contact-row">${icon('phone')}<div>${VENDOR_CONTACTS.phones.map(p => `<a href="tel:${p.replace(/[^\d+]/g, '')}">${esc(p)}</a>`).join('<br>')}</div></div>
|
|
639
|
-
<div class="contact-row">${icon('globe')}<div><a href="${esc(VENDOR_CONTACTS.site)}" target="_blank" rel="noopener">${esc(VENDOR_CONTACTS.site.replace(/^https?:\/\//, ''))}</a> · <a href="https://${esc(P.domain)}">${esc(P.domain)}</a></div></div>
|
|
640
|
-
</div>
|
|
641
|
-
</div>
|
|
642
|
-
</div>
|
|
643
|
-
</section>
|
|
644
|
-
|
|
645
493
|
<footer>
|
|
646
494
|
<div class="footer">
|
|
647
495
|
<div>
|
|
@@ -668,39 +516,54 @@ export function renderLandingPage({ publicKey = '', regions = null, assetVersion
|
|
|
668
516
|
</footer>
|
|
669
517
|
</div>
|
|
670
518
|
|
|
671
|
-
<!--
|
|
519
|
+
<!-- Вход / Регистрация в Личный кабинет по одноразовому коду на Email -->
|
|
672
520
|
<div class="modal" id="authModal" role="dialog" aria-modal="true" aria-labelledby="authTitle">
|
|
673
|
-
<div class="card" style="max-width:
|
|
521
|
+
<div class="card" style="max-width:460px">
|
|
674
522
|
<div class="modal-head">
|
|
675
523
|
<img src="/assets/odant-logo.png" alt="">
|
|
676
524
|
<div>
|
|
677
|
-
<h3 class="h3" id="authTitle" style="margin:0"
|
|
678
|
-
<div class="small muted" id="authSub"
|
|
525
|
+
<h3 class="h3" id="authTitle" style="margin:0">Вход / Регистрация</h3>
|
|
526
|
+
<div class="small muted" id="authSub">На ваш Email придёт одноразовый 6-значный код подтверждения</div>
|
|
679
527
|
</div>
|
|
680
528
|
</div>
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
529
|
+
|
|
530
|
+
<div id="authIntentNotice" class="small" style="display:none;padding:10px 12px;border-radius:10px;background:rgba(0,163,224,.12);border:1px solid rgba(0,163,224,.35);margin-bottom:4px"></div>
|
|
531
|
+
|
|
532
|
+
<div id="authStepEmail">
|
|
533
|
+
<div class="field">
|
|
534
|
+
<label for="authEmail">Ваш Email *</label>
|
|
535
|
+
<input type="email" id="authEmail" value="" placeholder="Введите ваш email (например, name@company.ru)" autocomplete="email" required>
|
|
536
|
+
</div>
|
|
537
|
+
|
|
538
|
+
<div class="oferta-check-box" style="margin-top:10px">
|
|
539
|
+
<label class="oferta-check-label">
|
|
540
|
+
<input type="checkbox" id="authOfertaCheck" checked>
|
|
541
|
+
<span>
|
|
542
|
+
Регистрируясь и входя в Личный кабинет, я принимаю условия <a href="#" data-action="open-oferta">Публичного договора-оферты ODANT-WORK (${esc(PUBLIC_OFERTA.version)})</a>.
|
|
543
|
+
</span>
|
|
544
|
+
</label>
|
|
545
|
+
</div>
|
|
546
|
+
|
|
547
|
+
<button class="btn btn-primary" style="width:100%;margin-top:12px" id="btnSendCode" data-action="send-code">Получить код на Email</button>
|
|
688
548
|
</div>
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
<
|
|
693
|
-
<
|
|
694
|
-
<
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
549
|
+
|
|
550
|
+
<div id="authStepCode" style="display:none">
|
|
551
|
+
<div class="small" id="authCodeSentNotice" style="padding:10px 12px;border-radius:10px;background:rgba(16,185,129,.12);color:var(--ok);margin-bottom:10px"></div>
|
|
552
|
+
<div class="field">
|
|
553
|
+
<label for="authCodeInput">Одноразовый код из письма (6 цифр) *</label>
|
|
554
|
+
<input type="text" id="authCodeInput" value="" placeholder="000000" maxlength="6" inputmode="numeric" autocomplete="one-time-code" style="font-size:20px;letter-spacing:6px;text-align:center;font-family:monospace">
|
|
555
|
+
</div>
|
|
556
|
+
<button class="btn btn-primary" style="width:100%;margin-top:10px" id="btnVerifyCode" data-action="verify-code">${icon('check')} Подтвердить код и войти</button>
|
|
557
|
+
<div style="display:flex;justify-content:space-between;margin-top:8px">
|
|
558
|
+
<button class="btn btn-ghost btn-sm" data-action="reset-auth-step">← Изменить Email</button>
|
|
559
|
+
<button class="btn btn-ghost btn-sm" data-action="send-code">Отправить код повторно</button>
|
|
560
|
+
</div>
|
|
698
561
|
</div>
|
|
562
|
+
|
|
699
563
|
<div class="status" id="authErrorMsg" style="color:var(--danger);min-height:18px;margin-top:6px"></div>
|
|
700
|
-
<div style="display:flex;gap:10px;margin-top:
|
|
701
|
-
<button class="btn btn-
|
|
702
|
-
<button class="btn btn-ghost
|
|
703
|
-
<button class="btn btn-ghost" data-action="auth-close">Закрыть</button>
|
|
564
|
+
<div style="display:flex;gap:10px;margin-top:6px;justify-content:flex-end;flex-wrap:wrap">
|
|
565
|
+
<button class="btn btn-ghost btn-sm" id="btnLogoutModal" data-action="logout" style="display:none">Выйти из аккаунта</button>
|
|
566
|
+
<button class="btn btn-ghost btn-sm" data-action="auth-close">Закрыть</button>
|
|
704
567
|
</div>
|
|
705
568
|
</div>
|
|
706
569
|
</div>
|
|
@@ -728,7 +591,7 @@ export function renderLandingPage({ publicKey = '', regions = null, assetVersion
|
|
|
728
591
|
</div>
|
|
729
592
|
</div>
|
|
730
593
|
<div style="display:flex;gap:10px;margin-top:14px;justify-content:flex-end;flex-wrap:wrap">
|
|
731
|
-
<button class="btn btn-primary" data-action="accept-from-oferta">${icon('check')} Принять условия
|
|
594
|
+
<button class="btn btn-primary" data-action="accept-from-oferta">${icon('check')} Принять условия оферты</button>
|
|
732
595
|
<button class="btn btn-ghost" data-action="oferta-close">Закрыть</button>
|
|
733
596
|
</div>
|
|
734
597
|
</div>
|