ваше сообщение коммита

This commit is contained in:
2025-09-02 15:33:18 +03:00
parent c007c0b296
commit a6360ccd2e
21 changed files with 1269 additions and 316 deletions

View File

@@ -68,13 +68,17 @@
<input v-else v-model="settings.embedding_model" placeholder="bge-base-zh" />
<label>Выбранные RAG-таблицы</label>
<select v-model="settings.selected_rag_tables" :multiple="false">
<option v-for="table in ragTables" :key="table.id" :value="table.id">{{ table.name }} (id: {{ table.id }})</option>
<option value="">Выберите таблицу</option>
<option v-for="table in ragTables" :key="table.id" :value="table.id">
{{ getTableDisplayName(table) }}
</option>
</select>
<label>Набор правил</label>
<div class="rules-row">
<select v-model="settings.rules_id">
<option value="">Выберите набор правил</option>
<option v-for="rule in rulesList" :key="rule.id" :value="rule.id">
{{ rule.name }}
{{ getRuleDisplayName(rule) }}
</option>
</select>
<button type="button" @click="openRuleEditor()">Создать</button>
@@ -150,7 +154,18 @@ async function loadRules() {
async function loadSettings() {
const { data } = await axios.get('/settings/ai-assistant');
if (data.success && data.settings) {
settings.value = data.settings;
// Обрабатываем selected_rag_tables - если это массив, берем первый элемент для single select
const settingsData = { ...data.settings };
if (Array.isArray(settingsData.selected_rag_tables) && settingsData.selected_rag_tables.length > 0) {
// Для single select берем первый элемент массива
settingsData.selected_rag_tables = settingsData.selected_rag_tables[0];
} else if (!Array.isArray(settingsData.selected_rag_tables)) {
// Если это не массив, устанавливаем пустое значение
settingsData.selected_rag_tables = '';
}
settings.value = settingsData;
console.log('[AiAssistantSettings] Loaded settings:', settings.value);
}
}
async function loadTelegramBots() {
@@ -204,7 +219,14 @@ onBeforeUnmount(() => {
window.removeEventListener('placeholders-updated', loadPlaceholders);
});
async function saveSettings() {
await axios.put('/settings/ai-assistant', settings.value);
// Преобразуем selected_rag_tables в массив перед сохранением
const settingsToSave = { ...settings.value };
if (settingsToSave.selected_rag_tables && !Array.isArray(settingsToSave.selected_rag_tables)) {
settingsToSave.selected_rag_tables = [settingsToSave.selected_rag_tables];
}
console.log('[AiAssistantSettings] Saving settings:', settingsToSave);
await axios.put('/settings/ai-assistant', settingsToSave);
goBack();
}
function openRuleEditor(ruleId = null) {
@@ -226,6 +248,16 @@ async function onRuleEditorClose(updated) {
editingRule.value = null;
if (updated) await loadRules();
}
function getTableDisplayName(table) {
if (!table) return '';
return table.name || `Таблица ${table.id}`;
}
function getRuleDisplayName(rule) {
if (!rule) return '';
return rule.name || `Набор правил ${rule.id}`;
}
</script>
<style scoped>

View File

@@ -41,6 +41,14 @@
<label for="imapPort">IMAP Port</label>
<input id="imapPort" v-model.number="form.imapPort" type="number" required />
</div>
<div class="form-group">
<label for="imapUser">IMAP User</label>
<input id="imapUser" v-model="form.imapUser" type="text" required />
</div>
<div class="form-group">
<label for="imapPassword">IMAP Password</label>
<input id="imapPassword" v-model="form.imapPassword" type="password" :placeholder="form.imapPassword ? 'Изменить пароль' : 'Введите пароль'" />
</div>
<div class="form-group">
<label for="fromEmail">From Email</label>
<input id="fromEmail" v-model="form.fromEmail" type="email" required />
@@ -54,6 +62,8 @@
<div class="view-row"><span>SMTP User:</span> <b>{{ form.smtpUser }}</b></div>
<div class="view-row"><span>IMAP Host:</span> <b>{{ form.imapHost }}</b></div>
<div class="view-row"><span>IMAP Port:</span> <b>{{ form.imapPort }}</b></div>
<div class="view-row"><span>IMAP User:</span> <b>{{ form.imapUser }}</b></div>
<div class="view-row"><span>IMAP Password:</span> <b>{{ form.imapPassword ? '••••••••' : 'Не установлен' }}</b></div>
<div class="view-row"><span>From Email:</span> <b>{{ form.fromEmail }}</b></div>
<button type="button" class="edit-btn" @click="editMode = true">Изменить</button>
<button type="button" class="cancel-btn" @click="goBack">Закрыть</button>
@@ -79,6 +89,8 @@ const form = reactive({
smtpPassword: '',
imapHost: '',
imapPort: 993,
imapUser: '',
imapPassword: '',
fromEmail: ''
});
const original = reactive({});
@@ -94,6 +106,8 @@ const loadEmailSettings = async () => {
form.smtpUser = s.smtp_user;
form.imapHost = s.imap_host || '';
form.imapPort = s.imap_port || 993;
form.imapUser = s.imap_user || '';
form.imapPassword = '';
form.fromEmail = s.from_email;
form.smtpPassword = '';
Object.assign(original, JSON.parse(JSON.stringify(form)));
@@ -117,10 +131,13 @@ const saveEmailSettings = async () => {
smtp_password: form.smtpPassword || undefined,
imap_host: form.imapHost,
imap_port: form.imapPort,
imap_user: form.imapUser,
imap_password: form.imapPassword || undefined,
from_email: form.fromEmail
});
alert('Настройки Email сохранены');
form.smtpPassword = '';
form.imapPassword = '';
Object.assign(original, JSON.parse(JSON.stringify(form)));
editMode.value = false;
} catch (e) {
@@ -131,6 +148,7 @@ const saveEmailSettings = async () => {
const cancelEdit = () => {
Object.assign(form, JSON.parse(JSON.stringify(original)));
form.smtpPassword = '';
form.imapPassword = '';
editMode.value = false;
};
</script>

View File

@@ -76,7 +76,7 @@ onMounted(async () => {
const saveTelegramSettings = async () => {
try {
await api.put('/telegram-settings', {
await api.put('/settings/telegram-settings', {
bot_token: form.botToken,
bot_username: form.botUsername
});