Fixed RPG
This commit is contained in:
+154
-26
@@ -1,10 +1,25 @@
|
||||
import { currentPersona, setCurrentPersona, sessionId } from './state.js';
|
||||
import { initChat } from './chat.js';
|
||||
import { initWizard } from './utils.js';
|
||||
import { initWizard, fillGreetingSelect, getSelectedGreeting } from './utils.js';
|
||||
|
||||
export let personaIndex = new Map();
|
||||
|
||||
function parseAlternateGreetings(p) {
|
||||
if (Array.isArray(p?.alternate_greetings) && p.alternate_greetings.length) {
|
||||
return p.alternate_greetings;
|
||||
}
|
||||
try {
|
||||
const parsed = JSON.parse(p?.alternate_greetings_json || '[]');
|
||||
return Array.isArray(parsed) ? parsed : [];
|
||||
} catch {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
let createWizard;
|
||||
let cardImportWizard;
|
||||
let cardPreview = null;
|
||||
let cardImportFile = null;
|
||||
|
||||
export function highlightPersona(personaId) {
|
||||
document.querySelectorAll('.persona-card').forEach(c => {
|
||||
@@ -15,7 +30,10 @@ export function highlightPersona(personaId) {
|
||||
export async function loadPersonas() {
|
||||
const res = await fetch('/personas/');
|
||||
const personas = await res.json();
|
||||
personaIndex = new Map(personas.map(p => [p.persona_id, p]));
|
||||
personaIndex = new Map(personas.map(p => {
|
||||
const alternate_greetings = parseAlternateGreetings(p);
|
||||
return [p.persona_id, { ...p, alternate_greetings }];
|
||||
}));
|
||||
const bar = document.getElementById('personaBar');
|
||||
bar.innerHTML = '';
|
||||
|
||||
@@ -55,6 +73,19 @@ export async function loadPersonas() {
|
||||
document.getElementById('editAppearance').value = data.appearance_tags || '';
|
||||
document.getElementById('editLora').value = data.lora_name || '';
|
||||
document.getElementById('editLoraWeight').value = data.lora_weight ?? 0.8;
|
||||
const alts = data.alternate_greetings || [];
|
||||
const altBlock = document.getElementById('editCardAltBlock');
|
||||
const altSelect = document.getElementById('editCardGreetingSelect');
|
||||
if (alts.length) {
|
||||
altBlock?.classList.remove('hidden');
|
||||
fillGreetingSelect(altSelect, data.first_mes, alts);
|
||||
altSelect.onchange = () => {
|
||||
document.getElementById('editFirstMes').value =
|
||||
getSelectedGreeting(altSelect, data.first_mes, alts);
|
||||
};
|
||||
} else {
|
||||
altBlock?.classList.add('hidden');
|
||||
}
|
||||
document.getElementById('cardEditOverlay').classList.add('open');
|
||||
});
|
||||
|
||||
@@ -95,7 +126,7 @@ export async function loadPersonas() {
|
||||
importBtn.type = 'button';
|
||||
importBtn.className = 'card-import-btn';
|
||||
importBtn.innerHTML = '📥<span>Chub</span>';
|
||||
importBtn.addEventListener('click', () => document.getElementById('cardModalOverlay').classList.add('open'));
|
||||
importBtn.addEventListener('click', () => openCardImportModal());
|
||||
bar.appendChild(importBtn);
|
||||
}
|
||||
|
||||
@@ -112,6 +143,122 @@ export async function selectPersona(personaId) {
|
||||
}
|
||||
}
|
||||
|
||||
function fillImpCardForm(preview) {
|
||||
document.getElementById('impCardName').value = preview.name || '';
|
||||
document.getElementById('impCardDescription').value = preview.description || '';
|
||||
document.getElementById('impCardPersonality').value = preview.personality || '';
|
||||
document.getElementById('impCardScenario').value = preview.scenario || '';
|
||||
document.getElementById('impCardMesExample').value = preview.mes_example || '';
|
||||
document.getElementById('impCardAppearance').value = preview.appearance_tags || '';
|
||||
|
||||
const alts = preview.alternate_greetings || [];
|
||||
const selectEl = document.getElementById('impCardGreetingSelect');
|
||||
const firstMesEl = document.getElementById('impCardFirstMes');
|
||||
fillGreetingSelect(selectEl, preview.first_mes, alts);
|
||||
firstMesEl.value = preview.first_mes || '';
|
||||
|
||||
const altHint = document.getElementById('impCardAltHint');
|
||||
if (alts.length) {
|
||||
altHint.textContent = `В карточке ${alts.length} альтернативных приветствий — выбери в списке или отредактируй текст ниже`;
|
||||
altHint.classList.remove('hidden');
|
||||
} else {
|
||||
altHint.classList.add('hidden');
|
||||
}
|
||||
|
||||
selectEl.onchange = () => {
|
||||
firstMesEl.value = getSelectedGreeting(selectEl, preview.first_mes, alts);
|
||||
};
|
||||
}
|
||||
|
||||
async function loadCardPreview() {
|
||||
const fileInput = document.getElementById('cardFile');
|
||||
if (!fileInput.files?.length) {
|
||||
alert('Выберите файл карточки (JSON или PNG)');
|
||||
return false;
|
||||
}
|
||||
const form = new FormData();
|
||||
form.append('file', fileInput.files[0]);
|
||||
const res = await fetch('/characters/preview', { method: 'POST', body: form });
|
||||
const data = await res.json();
|
||||
if (!res.ok) {
|
||||
alert(data.detail || 'Ошибка чтения карточки');
|
||||
return false;
|
||||
}
|
||||
cardPreview = data;
|
||||
cardImportFile = fileInput.files[0];
|
||||
fillImpCardForm(data);
|
||||
const hint = document.getElementById('cardPreviewHint');
|
||||
if (hint) {
|
||||
hint.textContent = `${data.name} · ${data.alternate_count || 0} альт. приветствий`;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function openCardImportModal() {
|
||||
cardPreview = null;
|
||||
cardImportFile = null;
|
||||
document.getElementById('cardFile').value = '';
|
||||
document.getElementById('cardPreviewHint').textContent = '';
|
||||
document.getElementById('cardLora').value = '';
|
||||
document.getElementById('cardLoraWeight').value = '0.8';
|
||||
cardImportWizard?.reset();
|
||||
document.getElementById('cardModalOverlay').classList.add('open');
|
||||
}
|
||||
|
||||
function closeCardImportModal() {
|
||||
document.getElementById('cardModalOverlay').classList.remove('open');
|
||||
cardImportWizard?.reset();
|
||||
cardPreview = null;
|
||||
cardImportFile = null;
|
||||
}
|
||||
|
||||
function initCardImportWizard() {
|
||||
const modal = document.getElementById('cardModalOverlay')?.querySelector('.modal-wizard');
|
||||
if (!modal) return;
|
||||
|
||||
cardImportWizard = initWizard(modal, {
|
||||
totalSteps: 2,
|
||||
validateStep(step) {
|
||||
if (step !== 1) return true;
|
||||
return loadCardPreview();
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
async function submitCardImport() {
|
||||
if (!cardImportFile || !cardPreview) {
|
||||
alert('Сначала загрузите и проверьте карточку');
|
||||
return;
|
||||
}
|
||||
const form = new FormData();
|
||||
form.append('file', cardImportFile);
|
||||
form.append('card_id', cardPreview.card_id || '');
|
||||
form.append('lora_name', document.getElementById('cardLora').value.trim());
|
||||
form.append('lora_weight', document.getElementById('cardLoraWeight').value || '0.8');
|
||||
form.append('name', document.getElementById('impCardName').value.trim());
|
||||
form.append('description', document.getElementById('impCardDescription').value.trim());
|
||||
form.append('personality', document.getElementById('impCardPersonality').value.trim());
|
||||
form.append('scenario', document.getElementById('impCardScenario').value.trim());
|
||||
form.append('first_mes', document.getElementById('impCardFirstMes').value.trim());
|
||||
form.append('mes_example', document.getElementById('impCardMesExample').value.trim());
|
||||
form.append('appearance_tags', document.getElementById('impCardAppearance').value.trim());
|
||||
form.append(
|
||||
'alternate_greetings_json',
|
||||
JSON.stringify(cardPreview.alternate_greetings || []),
|
||||
);
|
||||
|
||||
const res = await fetch('/characters/import', { method: 'POST', body: form });
|
||||
const data = await res.json();
|
||||
if (!res.ok) {
|
||||
alert(data.detail || 'Ошибка импорта');
|
||||
return;
|
||||
}
|
||||
closeCardImportModal();
|
||||
document.getElementById('cardFile').value = '';
|
||||
await loadPersonas();
|
||||
await selectPersona(data.persona_id);
|
||||
}
|
||||
|
||||
export function initPersonaModals() {
|
||||
const createModal = document.getElementById('modalOverlay');
|
||||
createWizard = initWizard(createModal.querySelector('.modal-wizard'), {
|
||||
@@ -132,8 +279,10 @@ export function initPersonaModals() {
|
||||
createModal.classList.remove('open');
|
||||
createWizard.reset();
|
||||
});
|
||||
initCardImportWizard();
|
||||
|
||||
document.getElementById('cardModalCancel').addEventListener('click', () => {
|
||||
document.getElementById('cardModalOverlay').classList.remove('open');
|
||||
closeCardImportModal();
|
||||
});
|
||||
document.getElementById('cardEditCancel').addEventListener('click', () => {
|
||||
document.getElementById('cardEditOverlay').classList.remove('open');
|
||||
@@ -210,28 +359,7 @@ export function initPersonaModals() {
|
||||
await loadPersonas();
|
||||
});
|
||||
|
||||
document.getElementById('cardModalImport').addEventListener('click', async () => {
|
||||
const fileInput = document.getElementById('cardFile');
|
||||
if (!fileInput.files?.length) {
|
||||
alert('Выберите файл карточки (JSON или PNG)');
|
||||
return;
|
||||
}
|
||||
const form = new FormData();
|
||||
form.append('file', fileInput.files[0]);
|
||||
form.append('lora_name', document.getElementById('cardLora').value.trim());
|
||||
form.append('lora_weight', document.getElementById('cardLoraWeight').value || '0.8');
|
||||
|
||||
const res = await fetch('/characters/import', { method: 'POST', body: form });
|
||||
const data = await res.json();
|
||||
if (!res.ok) {
|
||||
alert(data.detail || 'Ошибка импорта');
|
||||
return;
|
||||
}
|
||||
document.getElementById('cardModalOverlay').classList.remove('open');
|
||||
fileInput.value = '';
|
||||
await loadPersonas();
|
||||
await selectPersona(data.persona_id);
|
||||
});
|
||||
document.getElementById('cardModalImport').addEventListener('click', submitCardImport);
|
||||
|
||||
const personaEditSave = document.getElementById('personaEditSave');
|
||||
if (personaEditSave) {
|
||||
|
||||
Reference in New Issue
Block a user