diff --git a/components/ChannelEdit.js b/components/ChannelEdit.js
index 5d33550..a429794 100644
--- a/components/ChannelEdit.js
+++ b/components/ChannelEdit.js
@@ -63,6 +63,7 @@ const IMAGE_PALETTES = [
const TABS = [
{ id: 'content', label: 'Контент', icon: Type },
{ id: 'images', label: 'Картинки', icon: ImageIcon },
+ { id: 'ai', label: 'AI-стиль', icon: Sparkles },
{ id: 'connect', label: 'Подключение', icon: Plug },
];
@@ -106,6 +107,10 @@ export default function ChannelEdit({ channel }) {
const [tokenVerifying, setTokenVerifying] = useState(false);
const [tokenStatus, setTokenStatus] = useState(null); // null | 'ok' | 'error'
+ // AI-стиль
+ const [aiStylePrompt, setAiStylePrompt] = useState(channel.ai_style_prompt || '');
+ const [imageQuality, setImageQuality] = useState(channel.image_quality || 'standard');
+
const [saving, setSaving] = useState(false);
const [deleting, setDeleting] = useState(false);
const [error, setError] = useState('');
@@ -121,6 +126,8 @@ export default function ChannelEdit({ channel }) {
tg_channel_id: tgChannelId.trim() || null,
tg_username: tgUsername.trim() || null,
vk_access_token: vkToken.trim() || null,
+ ai_style_prompt: aiStylePrompt.trim() || null,
+ image_quality: imageQuality,
style: {
tone, formality, humor,
post_length: postLength,
@@ -442,6 +449,84 @@ export default function ChannelEdit({ channel }) {
)}
+ {/* TAB: AI-стиль */}
+ {tab === 'ai' && (
+
+ {/* Промт для генерации статей */}
+
+
+
+
Стиль генерации статей
+
+
+ Дополнительные инструкции для AI при автоматической генерации статей в этом канале.
+ Применяется ко всем статьям канала. При ручной генерации можно переопределить.
+
+
+
+ {/* Качество изображений */}
+
+
+
+
Качество генерации картинок
+
+
+ {[
+ {
+ v: 'standard',
+ label: 'Стандарт',
+ model: 'gpt-5-image-mini',
+ desc: 'Быстро, дешевле. Подходит для большинства постов в TG и ВК.',
+ cost: '3 кредита / картинка',
+ badge: 'Рекомендуется',
+ },
+ {
+ v: 'hd',
+ label: 'HD',
+ model: 'gpt-5.4-image-2',
+ desc: 'Лучшее качество, фотореализм, поддержка текста на картинке.',
+ cost: '10 кредитов / картинка',
+ badge: 'Для текста на фото',
+ },
+ ].map(opt => (
+
setImageQuality(opt.v)}
+ className={`p-4 rounded-xl border text-left transition-all ${
+ imageQuality === opt.v
+ ? 'border-accent bg-accent/10'
+ : 'border-border hover:border-accent/40'
+ }`}
+ >
+
+ {opt.label}
+ {opt.badge}
+
+ {opt.model}
+ {opt.desc}
+ {opt.cost}
+
+ ))}
+
+
+
+ )}
+
{/* TAB: Подключение */}
{tab === 'connect' && (
diff --git a/components/ChannelView.js b/components/ChannelView.js
index 695f523..28bb551 100644
--- a/components/ChannelView.js
+++ b/components/ChannelView.js
@@ -38,6 +38,8 @@ function stripCaption(text) {
export default function ChannelView({ channel }) {
const [topic, setTopic] = useState('');
+ const [customPrompt, setCustomPrompt] = useState('');
+ const [showCustomPrompt, setShowCustomPrompt] = useState(false);
const [generating, setGenerating] = useState(false);
const [post, setPost] = useState(null);
const [error, setError] = useState('');
@@ -225,6 +227,7 @@ export default function ChannelView({ channel }) {
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
type: 'post', channelId: channel.id, topic: useTopic, useCritique: true,
+ customPrompt: customPrompt.trim() || undefined,
}),
});
const job = await createRes.json();
@@ -407,12 +410,42 @@ export default function ChannelView({ channel }) {
)}