MP Manager Cluster Auto Strategy Setter

Автоматическая установка стратегии рекламной кампании на основе статистики

Size

110.8 KB

Version

1.8.33

Created

Feb 12, 2026

Updated

about 1 month ago

1// ==UserScript==
2// @name		MP Manager Cluster Auto Strategy Setter
3// @description		Автоматическая установка стратегии рекламной кампании на основе статистики
4// @version		1.8.33
5// @match		https://*.app.mpmgr.ru/*
6// @icon		https://app.mpmgr.ru/favicon.ico
7// @grant		GM.getValue
8// @grant		GM.setValue
9// @grant		GM.deleteValue
10// @grant		GM.openInTab
11// @grant		GM.setClipboard
12// ==/UserScript==
13(function() {
14    'use strict';
15
16    console.log('MP Manager Auto Strategy Setter загружен');
17
18    // Константы
19    const STRATEGY_CODE = 'eyJjYW1wYWlnblR5cGUiOiJTZWFyY2hDYXRhbG9nIiwidmVyc2lvbiI6MiwiZGF0YSI6eyJzdGF0ZSI6IkVuYWJsZWQiLCJtb2RlIjp7InR5cGUiOiJQb3NpdGlvbiIsInBhdXNlVHlwZSI6IlJlc3VtZSJ9LCJzdHJhdGVneSI6eyJ0eXBlIjoiQ2FtcGFpZ25TdGF0cyIsIm1vZGUiOiJQbGFjZSIsImJpZE1vZGUiOiJDb3N0UGVyQ2xpY2siLCJjYW1wYWlnblN0YXRzIjp7Im1heFByaWNlIjo2MCwibWluUHJpY2UiOjEsInBsYXRmb3JtcyI6W10sImludGVydmFsIjoiV2VlayIsInJ1bGVzIjpbeyJ0eXBlIjoiQ29zdFBlckFkZGVkVG9DYXJ0IiwibW9kZSI6IlZhbHVlIiwidmFsdWUiOiIifV19fSwicGxhY2VTdHJhdGVneSI6eyJ0eXBlIjoiS2V5d29yZHMiLCJrZXl3b3JkcyI6eyJrZXl3b3JkcyI6W119fSwiaXNDbHVzdGVyIjpmYWxzZX19';
20    const CLUSTER_STRATEGY_CODE = 'eyJjYW1wYWlnblR5cGUiOiJTZWFyY2hDYXRhbG9nIiwidmVyc2lvbiI6MiwiZGF0YSI6eyJzdGF0ZSI6IkVuYWJsZWQiLCJtb2RlIjp7InR5cGUiOiJQb3NpdGlvbiIsInBhdXNlVHlwZSI6IlJlc3VtZSJ9LCJzdHJhdGVneSI6eyJ0eXBlIjoiQ2FtcGFpZ25TdGF0cyIsIm1vZGUiOiJQbGFjZSIsImJpZE1vZGUiOiJDb3N0UGVyQ2xpY2siLCJjbHVzdGVyU3RhdHMiOnsibWF4QmlkIjo4MDAwLCJtaW5CaWQiOjQwMCwiaW50ZXJ2YWwiOiJUaHJlZURheXMiLCJydWxlcyI6W3sidHlwZSI6IkF2ZXJhZ2VQb3NpdGlvbiIsIm1vZGUiOiJWYWx1ZSIsInZhbHVlIjoyfSx7InR5cGUiOiJDb3N0UGVyQWRkZWRUb0NhcnQiLCJtb2RlIjoiQXZlcmFnZVZhbHVlIn1dfSwiY2FtcGFpZ25TdGF0cyI6eyJtYXhCaWQiOjgwMDAsIm1pbkJpZCI6NDAwLCJpbnRlcnZhbCI6IldlZWsiLCJydWxlcyI6W3sidHlwZSI6IkNvc3RQZXJBZGRlZFRvQ2FydCIsIm1vZGUiOiJWYWx1ZSIsInZhbHVlIjoiIn1dLCJtYXhQcmljZSI6IjEwMCIsIm1pblByaWNlIjoiMSIsInBsYXRmb3JtcyI6W119fSwicGxhY2VTdHJhdGVneSI6eyJ0eXBlIjoiS2V5d29yZHMiLCJrZXl3b3JkcyI6eyJrZXl3b3JkcyI6W119fSwiaXNDbHVzdGVyIjp0cnVlfX0=';
21
22    // Глобальные переменные для массовой обработки
23    let isBulkProcessing = false;
24    let bulkDesiredPercentage = 30;
25    let bulkPaused = false;
26
27    // Функция для получения сохраненных стратегий
28    async function getSavedStrategies() {
29        let strategies = await GM.getValue('saved_strategies', []);
30        
31        // Миграция: добавляем ID к стратегиям, у которых его нет
32        let needsMigration = false;
33        strategies = strategies.map((strategy, index) => {
34            if (!strategy.id) {
35                needsMigration = true;
36                return {
37                    ...strategy,
38                    id: 'strategy_migrated_' + Date.now() + '_' + index
39                };
40            }
41            return strategy;
42        });
43        
44        // Сохраняем обновленные стратегии, если была миграция
45        if (needsMigration) {
46            await GM.setValue('saved_strategies', strategies);
47            console.log('Миграция стратегий выполнена: добавлены ID');
48        }
49        
50        // Если нет сохраненных стратегий, добавляем стратегию по умолчанию
51        if (strategies.length === 0) {
52            return [{
53                id: 'default',
54                name: 'Стратегия по умолчанию',
55                data: STRATEGY_CODE
56            }];
57        }
58        return strategies;
59    }
60
61    // Функция для получения сохраненных стратегий для кластеров
62    async function getSavedClusterStrategies() {
63        let strategies = await GM.getValue('saved_cluster_strategies', []);
64        
65        // Миграция: добавляем ID к стратегиям, у которых его нет
66        let needsMigration = false;
67        strategies = strategies.map((strategy, index) => {
68            if (!strategy.id) {
69                needsMigration = true;
70                return {
71                    ...strategy,
72                    id: 'cluster_strategy_migrated_' + Date.now() + '_' + index
73                };
74            }
75            return strategy;
76        });
77        
78        // Сохраняем обновленные стратегии, если была миграция
79        if (needsMigration) {
80            await GM.setValue('saved_cluster_strategies', strategies);
81            console.log('Миграция кластерных стратегий выполнена: добавлены ID');
82        }
83        
84        // Если нет сохраненных стратегий, добавляем стратегию по умолчанию
85        if (strategies.length === 0) {
86            return [{
87                id: 'cluster_default',
88                name: 'Кластерная стратегия по умолчанию',
89                data: CLUSTER_STRATEGY_CODE
90            }];
91        }
92        return strategies;
93    }
94
95    // Функция для получения текущей стратегии
96    async function getCurrentStrategy() {
97        const currentId = await GM.getValue('current_strategy_id', 'default');
98        const strategies = await getSavedStrategies();
99        const strategy = strategies.find(s => s.id === currentId);
100        return strategy ? strategy.data : STRATEGY_CODE;
101    }
102
103    // Функция для получения текущей кластерной стратегии
104    async function getCurrentClusterStrategy() {
105        const currentId = await GM.getValue('current_cluster_strategy_id', 'cluster_default');
106        const strategies = await getSavedClusterStrategies();
107        const strategy = strategies.find(s => s.id === currentId);
108        return strategy ? strategy.data : CLUSTER_STRATEGY_CODE;
109    }
110
111    // Функция для создания модального окна управления стратегиями
112    function createStrategyManagementModal() {
113        return new Promise(async (resolve) => {
114            // Создаем оверлей
115            const overlay = document.createElement('div');
116            overlay.style.cssText = `
117                position: fixed;
118                top: 0;
119                left: 0;
120                width: 100%;
121                height: 100%;
122                background: rgba(0, 0, 0, 0.5);
123                display: flex;
124                justify-content: center;
125                align-items: center;
126                z-index: 10001;
127            `;
128            
129            // Создаем модальное окно
130            const modal = document.createElement('div');
131            modal.style.cssText = `
132                background: white;
133                border-radius: 12px;
134                padding: 24px;
135                min-width: 500px;
136                max-width: 600px;
137                max-height: 80vh;
138                overflow-y: auto;
139                box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);
140            `;
141            
142            // Заголовок
143            const title = document.createElement('h2');
144            title.textContent = 'Управление стратегиями';
145            title.style.cssText = `
146                margin: 0 0 20px 0;
147                font-size: 24px;
148                font-weight: bold;
149                color: #333;
150            `;
151            modal.appendChild(title);
152            
153            // Контейнер для списка стратегий
154            const listContainer = document.createElement('div');
155            listContainer.style.cssText = `
156                margin-bottom: 20px;
157                max-height: 300px;
158                overflow-y: auto;
159            `;
160            
161            // Функция для обновления списка
162            const updateList = async () => {
163                const currentStrategies = await getSavedStrategies();
164                const selectedStrategy = await GM.getValue('current_strategy_id', 'default');
165                listContainer.innerHTML = '';
166                
167                if (currentStrategies.length === 0) {
168                    const emptyMessage = document.createElement('p');
169                    emptyMessage.textContent = 'Нет сохраненных стратегий. Используется стратегия по умолчанию.';
170                    emptyMessage.style.cssText = `
171                        color: #666;
172                        font-style: italic;
173                        padding: 20px;
174                        text-align: center;
175                    `;
176                    listContainer.appendChild(emptyMessage);
177                } else {
178                    currentStrategies.forEach((strategy, index) => {
179                        const item = document.createElement('div');
180                        const isSelected = strategy.id === selectedStrategy;
181                        item.style.cssText = `
182                            display: flex;
183                            justify-content: space-between;
184                            align-items: center;
185                            padding: 12px;
186                            margin-bottom: 8px;
187                            background: ${isSelected ? '#e3f2fd' : '#f5f5f5'};
188                            border-radius: 8px;
189                            border: ${isSelected ? '2px solid #2196f3' : '1px solid #ddd'};
190                        `;
191                        
192                        const nameSpan = document.createElement('span');
193                        nameSpan.textContent = strategy.name + (isSelected ? ' ✓' : '');
194                        nameSpan.style.cssText = `
195                            font-size: 16px;
196                            color: #333;
197                            flex: 1;
198                            font-weight: ${isSelected ? 'bold' : 'normal'};
199                        `;
200                        
201                        const buttonsContainer = document.createElement('div');
202                        buttonsContainer.style.cssText = `
203                            display: flex;
204                            gap: 8px;
205                        `;
206                        
207                        // Кнопка выбора
208                        if (!isSelected) {
209                            const selectBtn = document.createElement('button');
210                            selectBtn.textContent = '✓ Выбрать';
211                            selectBtn.style.cssText = `
212                                background: #2196f3;
213                                color: white;
214                                border: none;
215                                padding: 6px 12px;
216                                border-radius: 6px;
217                                cursor: pointer;
218                                font-size: 14px;
219                            `;
220                            selectBtn.onmouseover = () => selectBtn.style.background = '#1976d2';
221                            selectBtn.onmouseout = () => selectBtn.style.background = '#2196f3';
222                            selectBtn.onclick = async () => {
223                                await GM.setValue('current_strategy_id', strategy.id);
224                                console.log(`Выбрана стратегия: ${strategy.name} (ID: ${strategy.id})`);
225                                await updateList();
226                            };
227                            buttonsContainer.appendChild(selectBtn);
228                        }
229                        
230                        // Кнопка удаления
231                        const deleteBtn = document.createElement('button');
232                        deleteBtn.textContent = '🗑️';
233                        deleteBtn.style.cssText = `
234                            background: #f44336;
235                            color: white;
236                            border: none;
237                            padding: 6px 12px;
238                            border-radius: 6px;
239                            cursor: pointer;
240                            font-size: 14px;
241                        `;
242                        deleteBtn.onmouseover = () => deleteBtn.style.background = '#d32f2f';
243                        deleteBtn.onmouseout = () => deleteBtn.style.background = '#f44336';
244                        deleteBtn.onclick = async () => {
245                            if (confirm(`Удалить стратегию "${strategy.name}"?`)) {
246                                currentStrategies.splice(index, 1);
247                                await GM.setValue('saved_strategies', currentStrategies);
248                                // Если удаляем выбранную стратегию, возвращаемся к дефолтной
249                                if (isSelected) {
250                                    await GM.setValue('current_strategy_id', 'default');
251                                }
252                                await updateList();
253                            }
254                        };
255                        buttonsContainer.appendChild(deleteBtn);
256                        
257                        item.appendChild(nameSpan);
258                        item.appendChild(buttonsContainer);
259                        listContainer.appendChild(item);
260                    });
261                }
262            };
263            
264            await updateList();
265            modal.appendChild(listContainer);
266            
267            // Кнопка добавления стратегии
268            const addButton = document.createElement('button');
269            addButton.textContent = '➕ Добавить новую стратегию';
270            addButton.style.cssText = `
271                width: 100%;
272                background: #4caf50;
273                color: white;
274                border: none;
275                padding: 12px;
276                border-radius: 8px;
277                cursor: pointer;
278                font-size: 16px;
279                font-weight: bold;
280                margin-bottom: 12px;
281            `;
282            addButton.onmouseover = () => addButton.style.background = '#45a049';
283            addButton.onmouseout = () => addButton.style.background = '#4caf50';
284            addButton.onclick = async () => {
285                const name = prompt('Введите название стратегии:');
286                if (!name) return;
287                
288                const data = prompt('Вставьте код стратегии (скопируйте из MP Manager):');
289                if (!data) return;
290                
291                const currentStrategies = await GM.getValue('saved_strategies', []);
292                const newId = 'strategy_' + Date.now() + '_' + Math.random().toString(36).substr(2, 9);
293                currentStrategies.push({ id: newId, name, data });
294                await GM.setValue('saved_strategies', currentStrategies);
295                alert(`Стратегия "${name}" сохранена!`);
296                await updateList();
297            };
298            modal.appendChild(addButton);
299            
300            // Кнопка закрытия
301            const closeButton = document.createElement('button');
302            closeButton.textContent = 'Закрыть';
303            closeButton.style.cssText = `
304                width: 100%;
305                background: #666;
306                color: white;
307                border: none;
308                padding: 12px;
309                border-radius: 8px;
310                cursor: pointer;
311                font-size: 16px;
312            `;
313            closeButton.onmouseover = () => closeButton.style.background = '#555';
314            closeButton.onmouseout = () => closeButton.style.background = '#666';
315            closeButton.onclick = () => {
316                document.body.removeChild(overlay);
317                resolve();
318            };
319            modal.appendChild(closeButton);
320            
321            overlay.appendChild(modal);
322            document.body.appendChild(overlay);
323            
324            // Закрытие по клику на оверлей
325            overlay.onclick = (e) => {
326                if (e.target === overlay) {
327                    document.body.removeChild(overlay);
328                    resolve();
329                }
330            };
331        });
332    }
333
334    // Функция для создания модального окна управления кластерными стратегиями
335    function createClusterStrategyManagementModal() {
336        return new Promise(async (resolve) => {
337            // Создаем оверлей
338            const overlay = document.createElement('div');
339            overlay.style.cssText = `
340                position: fixed;
341                top: 0;
342                left: 0;
343                width: 100%;
344                height: 100%;
345                background: rgba(0, 0, 0, 0.5);
346                display: flex;
347                justify-content: center;
348                align-items: center;
349                z-index: 10001;
350            `;
351            
352            // Создаем модальное окно
353            const modal = document.createElement('div');
354            modal.style.cssText = `
355                background: white;
356                border-radius: 12px;
357                padding: 24px;
358                min-width: 500px;
359                max-width: 600px;
360                max-height: 80vh;
361                overflow-y: auto;
362                box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);
363            `;
364            
365            // Заголовок
366            const title = document.createElement('h2');
367            title.textContent = 'Управление стратегиями для кластеров';
368            title.style.cssText = `
369                margin: 0 0 20px 0;
370                font-size: 24px;
371                font-weight: bold;
372                color: #333;
373            `;
374            modal.appendChild(title);
375            
376            // Контейнер для списка стратегий
377            const listContainer = document.createElement('div');
378            listContainer.style.cssText = `
379                margin-bottom: 20px;
380                max-height: 300px;
381                overflow-y: auto;
382            `;
383            
384            // Функция для обновления списка
385            const updateList = async () => {
386                const currentStrategies = await getSavedClusterStrategies();
387                const selectedStrategy = await GM.getValue('current_cluster_strategy_id', 'cluster_default');
388                listContainer.innerHTML = '';
389                
390                if (currentStrategies.length === 0) {
391                    const emptyMessage = document.createElement('p');
392                    emptyMessage.textContent = 'Нет сохраненных стратегий. Используется стратегия по умолчанию.';
393                    emptyMessage.style.cssText = `
394                        color: #666;
395                        font-style: italic;
396                        padding: 20px;
397                        text-align: center;
398                    `;
399                    listContainer.appendChild(emptyMessage);
400                } else {
401                    currentStrategies.forEach((strategy, index) => {
402                        const item = document.createElement('div');
403                        const isSelected = strategy.id === selectedStrategy;
404                        item.style.cssText = `
405                            display: flex;
406                            justify-content: space-between;
407                            align-items: center;
408                            padding: 12px;
409                            margin-bottom: 8px;
410                            background: ${isSelected ? '#e3f2fd' : '#f5f5f5'};
411                            border-radius: 8px;
412                            border: ${isSelected ? '2px solid #2196f3' : '1px solid #ddd'};
413                        `;
414                        
415                        const nameSpan = document.createElement('span');
416                        nameSpan.textContent = strategy.name + (isSelected ? ' ✓' : '');
417                        nameSpan.style.cssText = `
418                            font-size: 16px;
419                            color: #333;
420                            flex: 1;
421                            font-weight: ${isSelected ? 'bold' : 'normal'};
422                        `;
423                        
424                        const buttonsContainer = document.createElement('div');
425                        buttonsContainer.style.cssText = `
426                            display: flex;
427                            gap: 8px;
428                        `;
429                        
430                        // Кнопка выбора
431                        if (!isSelected) {
432                            const selectBtn = document.createElement('button');
433                            selectBtn.textContent = '✓ Выбрать';
434                            selectBtn.style.cssText = `
435                                background: #2196f3;
436                                color: white;
437                                border: none;
438                                padding: 6px 12px;
439                                border-radius: 6px;
440                                cursor: pointer;
441                                font-size: 14px;
442                            `;
443                            selectBtn.onmouseover = () => selectBtn.style.background = '#1976d2';
444                            selectBtn.onmouseout = () => selectBtn.style.background = '#2196f3';
445                            selectBtn.onclick = async () => {
446                                await GM.setValue('current_cluster_strategy_id', strategy.id);
447                                console.log(`Выбрана кластерная стратегия: ${strategy.name} (ID: ${strategy.id})`);
448                                await updateList();
449                            };
450                            buttonsContainer.appendChild(selectBtn);
451                        }
452                        
453                        // Кнопка удаления
454                        const deleteBtn = document.createElement('button');
455                        deleteBtn.textContent = '🗑️';
456                        deleteBtn.style.cssText = `
457                            background: #f44336;
458                            color: white;
459                            border: none;
460                            padding: 6px 12px;
461                            border-radius: 6px;
462                            cursor: pointer;
463                            font-size: 14px;
464                        `;
465                        deleteBtn.onmouseover = () => deleteBtn.style.background = '#d32f2f';
466                        deleteBtn.onmouseout = () => deleteBtn.style.background = '#f44336';
467                        deleteBtn.onclick = async () => {
468                            if (confirm(`Удалить стратегию "${strategy.name}"?`)) {
469                                currentStrategies.splice(index, 1);
470                                await GM.setValue('saved_cluster_strategies', currentStrategies);
471                                // Если удаляем выбранную стратегию, возвращаемся к дефолтной
472                                if (isSelected) {
473                                    await GM.setValue('current_cluster_strategy_id', 'cluster_default');
474                                }
475                                await updateList();
476                            }
477                        };
478                        buttonsContainer.appendChild(deleteBtn);
479                        
480                        item.appendChild(nameSpan);
481                        item.appendChild(buttonsContainer);
482                        listContainer.appendChild(item);
483                    });
484                }
485            };
486            
487            await updateList();
488            modal.appendChild(listContainer);
489            
490            // Кнопка добавления стратегии
491            const addButton = document.createElement('button');
492            addButton.textContent = '➕ Добавить новую стратегию';
493            addButton.style.cssText = `
494                width: 100%;
495                background: #4caf50;
496                color: white;
497                border: none;
498                padding: 12px;
499                border-radius: 8px;
500                cursor: pointer;
501                font-size: 16px;
502                font-weight: bold;
503                margin-bottom: 12px;
504            `;
505            addButton.onmouseover = () => addButton.style.background = '#45a049';
506            addButton.onmouseout = () => addButton.style.background = '#4caf50';
507            addButton.onclick = async () => {
508                const name = prompt('Введите название стратегии для кластеров:');
509                if (!name) return;
510                
511                const data = prompt('Вставьте код стратегии (скопируйте из MP Manager):');
512                if (!data) return;
513                
514                const currentStrategies = await GM.getValue('saved_cluster_strategies', []);
515                const newId = 'cluster_strategy_' + Date.now() + '_' + Math.random().toString(36).substr(2, 9);
516                currentStrategies.push({ id: newId, name, data });
517                await GM.setValue('saved_cluster_strategies', currentStrategies);
518                alert(`Кластерная стратегия "${name}" сохранена!`);
519                await updateList();
520            };
521            modal.appendChild(addButton);
522            
523            // Кнопка закрытия
524            const closeButton = document.createElement('button');
525            closeButton.textContent = 'Закрыть';
526            closeButton.style.cssText = `
527                width: 100%;
528                background: #666;
529                color: white;
530                border: none;
531                padding: 12px;
532                border-radius: 8px;
533                cursor: pointer;
534                font-size: 16px;
535            `;
536            closeButton.onmouseover = () => closeButton.style.background = '#555';
537            closeButton.onmouseout = () => closeButton.style.background = '#666';
538            closeButton.onclick = () => {
539                document.body.removeChild(overlay);
540                resolve();
541            };
542            modal.appendChild(closeButton);
543            
544            overlay.appendChild(modal);
545            document.body.appendChild(overlay);
546            
547            // Закрытие по клику на оверлей
548            overlay.onclick = (e) => {
549                if (e.target === overlay) {
550                    document.body.removeChild(overlay);
551                    resolve();
552                }
553            };
554        });
555    }
556
557    // Функция для создания UI
558    function createUI() {
559        console.log('Создание UI панели');
560        
561        // Проверяем, есть ли сохраненный ДРР для массовой обработки
562        GM.getValue('bulkProcessingDRR', null).then(savedDRR => {
563            if (savedDRR !== null) {
564                console.log(`Найден сохраненный ДРР для массовой обработки: ${savedDRR}`);
565                // Автоматически запускаем стратегию с сохраненным ДРР
566                setTimeout(() => {
567                    const input = document.getElementById('desired-percentage');
568                    if (input) {
569                        input.value = savedDRR;
570                        // Запускаем стратегию автоматически
571                        runStrategy();
572                    }
573                }, 2000);
574            }
575        });
576        
577        const panel = document.createElement('div');
578        panel.id = 'auto-strategy-panel';
579        panel.style.cssText = `
580            position: fixed;
581            top: 20px;
582            right: 20px;
583            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
584            padding: 15px;
585            border-radius: 12px;
586            box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
587            z-index: 10000;
588            min-width: 280px;
589            font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
590            color: white;
591            transition: all 0.3s ease;
592            cursor: move;
593        `;
594
595        panel.innerHTML = `
596            <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 10px; cursor: pointer;" id="panel-header">
597                <h3 style="margin: 0; font-size: 16px; font-weight: 600;">🚀 Авто-стратегия</h3>
598                <span id="toggle-icon" style="font-size: 18px;"></span>
599            </div>
600            
601            <div id="panel-content" style="display: none;">
602                <div style="margin-bottom: 15px;">
603                    <label style="display: block; margin-bottom: 8px; font-size: 13px; font-weight: 500;">
604                        Желаемый % рекламных расходов:
605                    </label>
606                    <input 
607                        type="number" 
608                        id="desired-percentage" 
609                        value="30" 
610                        min="1" 
611                        max="100" 
612                        step="0.1"
613                        style="
614                            width: 100%;
615                            padding: 10px;
616                            border: none;
617                            border-radius: 8px;
618                            font-size: 14px;
619                            box-sizing: border-box;
620                            background: rgba(255, 255, 255, 0.95);
621                            color: #333;
622                            cursor: text;
623                        "
624                    />
625                </div>
626
627                <div style="margin-bottom: 15px;">
628                    <label style="display: flex; align-items: center; cursor: pointer; font-size: 13px; font-weight: 500;">
629                        <input 
630                            type="checkbox" 
631                            id="apply-to-clusters" 
632                            checked
633                            style="
634                                margin-right: 8px;
635                                width: 18px;
636                                height: 18px;
637                                cursor: pointer;
638                            "
639                        />
640                        Применить стратегию к кластерам
641                    </label>
642                </div>
643
644                <button 
645                    id="run-strategy-btn"
646                    style="
647                        width: 100%;
648                        padding: 12px;
649                        background: white;
650                        color: #667eea;
651                        border: none;
652                        border-radius: 8px;
653                        font-size: 14px;
654                        font-weight: 600;
655                        cursor: pointer;
656                        transition: all 0.3s ease;
657                        box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
658                        margin-bottom: 10px;
659                    "
660                    onmouseover="this.style.transform='translateY(-2px)'; this.style.boxShadow='0 6px 16px rgba(0, 0, 0, 0.2)';"
661                    onmouseout="this.style.transform='translateY(0)'; this.style.boxShadow='0 4px 12px rgba(0, 0, 0, 0.15)';"
662                >
663                    Запустить
664                </button>
665
666                <button 
667                    id="manage-strategies-btn"
668                    style="
669                        width: 100%;
670                        padding: 10px;
671                        background: rgba(255, 255, 255, 0.2);
672                        color: white;
673                        border: 1px solid rgba(255, 255, 255, 0.3);
674                        border-radius: 8px;
675                        font-size: 13px;
676                        font-weight: 600;
677                        cursor: pointer;
678                        transition: all 0.3s ease;
679                        margin-bottom: 8px;
680                    "
681                    onmouseover="this.style.background='rgba(255, 255, 255, 0.3)';"
682                    onmouseout="this.style.background='rgba(255, 255, 255, 0.2)';"
683                >
684                    ⚙️ Управление стратегиями
685                </button>
686
687                <button 
688                    id="manage-cluster-strategies-btn"
689                    style="
690                        width: 100%;
691                        padding: 10px;
692                        background: rgba(255, 255, 255, 0.2);
693                        color: white;
694                        border: 1px solid rgba(255, 255, 255, 0.3);
695                        border-radius: 8px;
696                        font-size: 13px;
697                        font-weight: 600;
698                        cursor: pointer;
699                        transition: all 0.3s ease;
700                    "
701                    onmouseover="this.style.background='rgba(255, 255, 255, 0.3)';"
702                    onmouseout="this.style.background='rgba(255, 255, 255, 0.2)';"
703                >
704                    🎯 Стратегии для кластеров
705                </button>
706
707                <div id="status-message" style="
708                    margin-top: 15px;
709                    padding: 10px;
710                    border-radius: 8px;
711                    font-size: 12px;
712                    background: rgba(255, 255, 255, 0.2);
713                    display: none;
714                "></div>
715            </div>
716        `;
717
718        document.body.appendChild(panel);
719        console.log('UI панель создана');
720
721        // Добавляем возможность перетаскивания
722        makeDraggable(panel);
723
724        // Добавляем обработчик клика на заголовок для разворачивания/сворачивания
725        document.getElementById('panel-header').addEventListener('click', () => {
726            const content = document.getElementById('panel-content');
727            const icon = document.getElementById('toggle-icon');
728            if (content.style.display === 'none') {
729                content.style.display = 'block';
730                icon.textContent = '▲';
731            } else {
732                content.style.display = 'none';
733                icon.textContent = '▼';
734            }
735        });
736
737        // Добавляем обработчик клика на кнопку
738        document.getElementById('run-strategy-btn').addEventListener('click', runStrategy);
739        
740        // Добавляем обработчик для кнопки управления стратегиями
741        document.getElementById('manage-strategies-btn').addEventListener('click', async () => {
742            await createStrategyManagementModal();
743        });
744        
745        // Добавляем обработчик для кнопки управления кластерными стратегиями
746        document.getElementById('manage-cluster-strategies-btn').addEventListener('click', async () => {
747            await createClusterStrategyManagementModal();
748        });
749    }
750
751    // Функция для создания UI панели массового изменения
752    function createBulkUI() {
753        console.log('Создание UI панели массового изменения');
754        
755        const panel = document.createElement('div');
756        panel.id = 'bulk-strategy-panel';
757        panel.style.cssText = `
758            position: fixed;
759            top: 20px;
760            right: 20px;
761            background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);
762            padding: 15px;
763            border-radius: 12px;
764            box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
765            z-index: 10000;
766            min-width: 300px;
767            font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
768            color: white;
769            transition: all 0.3s ease;
770            cursor: move;
771        `;
772
773        panel.innerHTML = `
774            <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 10px; cursor: pointer;" id="bulk-panel-header">
775                <h3 style="margin: 0; font-size: 16px; font-weight: 600;">📦 Массовое изменение</h3>
776                <span id="bulk-toggle-icon" style="font-size: 18px;"></span>
777            </div>
778            
779            <div id="bulk-panel-content" style="display: none;">
780                <div style="margin-bottom: 15px;">
781                    <label style="display: block; margin-bottom: 8px; font-size: 13px; font-weight: 500;">
782                        Желаемый % рекламных расходов (ДРР):
783                    </label>
784                    <input 
785                        type="number" 
786                        id="bulk-desired-percentage" 
787                        value="30" 
788                        min="1" 
789                        max="100" 
790                        step="0.1"
791                        style="
792                            width: 100%;
793                            padding: 10px;
794                            border: none;
795                            border-radius: 8px;
796                            font-size: 14px;
797                            box-sizing: border-box;
798                            background: rgba(255, 255, 255, 0.95);
799                            color: #333;
800                            cursor: text;
801                        "
802                    />
803                </div>
804
805                <div id="bulk-campaigns-info" style="
806                    margin-bottom: 15px;
807                    padding: 10px;
808                    border-radius: 8px;
809                    font-size: 12px;
810                    background: rgba(255, 255, 255, 0.2);
811                ">
812                    Найдено кампаний: <span id="campaigns-count">0</span>
813                </div>
814
815                <button 
816                    id="run-bulk-strategy-btn"
817                    style="
818                        width: 100%;
819                        padding: 12px;
820                        background: white;
821                        color: #f5576c;
822                        border: none;
823                        border-radius: 8px;
824                        font-size: 14px;
825                        font-weight: 600;
826                        cursor: pointer;
827                        transition: all 0.3s ease;
828                        box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
829                        margin-bottom: 10px;
830                    "
831                    onmouseover="this.style.transform='translateY(-2px)'; this.style.boxShadow='0 6px 16px rgba(0, 0, 0, 0.2)';"
832                    onmouseout="this.style.transform='translateY(0)'; this.style.boxShadow='0 4px 12px rgba(0, 0, 0, 0.15)';"
833                >
834                    Запустить
835                </button>
836
837                <button 
838                    id="bulk-manage-strategies-btn"
839                    style="
840                        width: 100%;
841                        padding: 10px;
842                        background: rgba(255, 255, 255, 0.2);
843                        color: white;
844                        border: 1px solid rgba(255, 255, 255, 0.3);
845                        border-radius: 8px;
846                        font-size: 13px;
847                        font-weight: 600;
848                        cursor: pointer;
849                        transition: all 0.3s ease;
850                        margin-bottom: 10px;
851                    "
852                    onmouseover="this.style.background='rgba(255, 255, 255, 0.3)';"
853                    onmouseout="this.style.background='rgba(255, 255, 255, 0.2)';"
854                >
855                    ⚙️ Управление стратегиями
856                </button>
857
858                <button 
859                    id="bulk-manage-cluster-strategies-btn"
860                    style="
861                        width: 100%;
862                        padding: 10px;
863                        background: rgba(255, 255, 255, 0.2);
864                        color: white;
865                        border: 1px solid rgba(255, 255, 255, 0.3);
866                        border-radius: 8px;
867                        font-size: 13px;
868                        font-weight: 600;
869                        cursor: pointer;
870                        transition: all 0.3s ease;
871                        margin-bottom: 10px;
872                    "
873                    onmouseover="this.style.background='rgba(255, 255, 255, 0.3)';"
874                    onmouseout="this.style.background='rgba(255, 255, 255, 0.2)';"
875                >
876                    🎯 Стратегии для кластеров
877                </button>
878
879                <div style="margin-bottom: 15px;">
880                    <label style="display: flex; align-items: center; cursor: pointer; font-size: 13px; font-weight: 500;">
881                        <input 
882                            type="checkbox" 
883                            id="bulk-apply-to-clusters" 
884                            checked
885                            style="
886                                margin-right: 8px;
887                                width: 18px;
888                                height: 18px;
889                                cursor: pointer;
890                            "
891                        />
892                        Применить стратегию к кластерам
893                    </label>
894                </div>
895
896                <div id="bulk-control-buttons" style="
897                    margin-top: 10px;
898                    display: none;
899                    gap: 10px;
900                ">
901                    <button 
902                        id="pause-bulk-btn"
903                        style="
904                            flex: 1;
905                            padding: 10px;
906                            background: rgba(255, 255, 255, 0.9);
907                            color: #f5576c;
908                            border: none;
909                            border-radius: 8px;
910                            font-size: 13px;
911                            font-weight: 600;
912                            cursor: pointer;
913                            transition: all 0.3s ease;
914                        "
915                    >
916                        ⏸️ Пауза
917                    </button>
918                    <button 
919                        id="stop-bulk-btn"
920                        style="
921                            flex: 1;
922                            padding: 10px;
923                            background: rgba(255, 59, 48, 0.9);
924                            color: white;
925                            border: none;
926                            border-radius: 8px;
927                            font-size: 13px;
928                            font-weight: 600;
929                            cursor: pointer;
930                            transition: all 0.3s ease;
931                        "
932                    >
933                        ⏹️ Стоп
934                    </button>
935                </div>
936
937                <div id="bulk-status-message" style="
938                    margin-top: 15px;
939                    padding: 10px;
940                    border-radius: 8px;
941                    font-size: 12px;
942                    background: rgba(255, 255, 255, 0.2);
943                    display: none;
944                "></div>
945
946                <div id="bulk-progress" style="
947                    margin-top: 15px;
948                    display: none;
949                ">
950                    <div style="margin-bottom: 5px; font-size: 12px;">
951                        Прогресс: <span id="bulk-progress-text">0/0</span>
952                    </div>
953                    <div style="
954                        width: 100%;
955                        height: 8px;
956                        background: rgba(255, 255, 255, 0.3);
957                        border-radius: 4px;
958                        overflow: hidden;
959                    ">
960                        <div id="bulk-progress-bar" style="
961                            width: 0%;
962                            height: 100%;
963                            background: white;
964                            transition: width 0.3s ease;
965                        "></div>
966                    </div>
967                </div>
968            </div>
969        `;
970
971        document.body.appendChild(panel);
972        console.log('UI панель массового изменения создана');
973
974        // Добавляем возможность перетаскивания
975        makeDraggable(panel);
976
977        // Подсчитываем количество кампаний
978        updateCampaignsCount();
979
980        // Добавляем обработчик клика на заголовок для разворачивания/сворачивания
981        document.getElementById('bulk-panel-header').addEventListener('click', () => {
982            const content = document.getElementById('bulk-panel-content');
983            const icon = document.getElementById('bulk-toggle-icon');
984            if (content.style.display === 'none') {
985                content.style.display = 'block';
986                icon.textContent = '▲';
987            } else {
988                content.style.display = 'none';
989                icon.textContent = '▼';
990            }
991        });
992
993        // Добавляем обработчик клика на кнопку
994        document.getElementById('run-bulk-strategy-btn').addEventListener('click', runBulkStrategy);
995        
996        // Добавляем обработчик для кнопки управления стратегиями
997        document.getElementById('bulk-manage-strategies-btn').addEventListener('click', async () => {
998            await createStrategyManagementModal();
999        });
1000        
1001        // Добавляем обработчик для кнопки управления кластерными стратегиями
1002        document.getElementById('bulk-manage-cluster-strategies-btn').addEventListener('click', async () => {
1003            await createClusterStrategyManagementModal();
1004        });
1005        
1006        // Добавляем обработчики для кнопок управления
1007        document.getElementById('pause-bulk-btn').addEventListener('click', pauseBulkProcessing);
1008        document.getElementById('stop-bulk-btn').addEventListener('click', stopBulkProcessing);
1009    }
1010
1011    // Функция для создания перетаскиваемого элемента
1012    function makeDraggable(element) {
1013        let pos1 = 0, pos2 = 0, pos3 = 0, pos4 = 0;
1014        let isDragging = false;
1015
1016        element.onmousedown = dragMouseDown;
1017
1018        function dragMouseDown(e) {
1019            // Не перетаскиваем, если кликнули на input, button или другие интерактивные элементы
1020            if (e.target.tagName === 'INPUT' || e.target.tagName === 'BUTTON' || e.target.tagName === 'TEXTAREA') {
1021                return;
1022            }
1023            
1024            e.preventDefault();
1025            isDragging = true;
1026            pos3 = e.clientX;
1027            pos4 = e.clientY;
1028            document.onmouseup = closeDragElement;
1029            document.onmousemove = elementDrag;
1030        }
1031
1032        function elementDrag(e) {
1033            if (!isDragging) return;
1034            pos1 = pos3 - e.clientX;
1035            pos2 = pos4 - e.clientY;
1036            pos3 = e.clientX;
1037            pos4 = e.clientY;
1038            element.style.top = (element.offsetTop - pos2) + 'px';
1039            element.style.left = (element.offsetLeft - pos1) + 'px';
1040            element.style.right = 'auto';
1041            element.style.bottom = 'auto';
1042        }
1043
1044        function closeDragElement() {
1045            isDragging = false;
1046            document.onmouseup = null;
1047            document.onmousemove = null;
1048        }
1049    }
1050
1051    // Функция для обновления количества кампаний
1052    function updateCampaignsCount() {
1053        const campaignLinks = document.querySelectorAll('a[href*="/campaigns/auto-campaigns/"][href*="/campaign"]');
1054        const count = campaignLinks.length;
1055        const countElement = document.getElementById('campaigns-count');
1056        if (countElement) {
1057            countElement.textContent = count;
1058        }
1059        console.log(`Найдено кампаний: ${count}`);
1060    }
1061
1062    // Функция для показа статуса массовой обработки
1063    function showBulkStatus(message, isError = false) {
1064        const statusDiv = document.getElementById('bulk-status-message');
1065        if (statusDiv) {
1066            statusDiv.textContent = message;
1067            statusDiv.style.display = 'block';
1068            statusDiv.style.background = isError ? 'rgba(255, 59, 48, 0.9)' : 'rgba(52, 199, 89, 0.9)';
1069            console.log(`Статус массовой обработки: ${message}`);
1070        }
1071    }
1072
1073    // Функция для обновления прогресса
1074    function updateBulkProgress(current, total) {
1075        const progressDiv = document.getElementById('bulk-progress');
1076        const progressText = document.getElementById('bulk-progress-text');
1077        const progressBar = document.getElementById('bulk-progress-bar');
1078        
1079        if (progressDiv && progressText && progressBar) {
1080            progressDiv.style.display = 'block';
1081            progressText.textContent = `${current}/${total}`;
1082            const percentage = (current / total) * 100;
1083            progressBar.style.width = `${percentage}%`;
1084        }
1085    }
1086
1087    // Функция для прокрутки страницы вниз для загрузки всех кампаний
1088    async function scrollToLoadAllCampaigns() {
1089        console.log('Начинаем загрузку всех кампаний через прокрутку...');
1090        
1091        // Находим контейнер с прокруткой
1092        const tableContainer = document.querySelector('.container.MuiBox-root.css-9hf803');
1093        
1094        if (!tableContainer) {
1095            console.error('Контейнер таблицы не найден');
1096            return [];
1097        }
1098        
1099        console.log('Контейнер найден, начинаем прокрутку...');
1100        console.log(`Высота контейнера: ${tableContainer.scrollHeight}px`);
1101        
1102        // Собираем уникальные ссылки во время прокрутки
1103        const uniqueLinks = new Set();
1104        
1105        // Прокручиваем контейнер постепенно, чтобы загрузить все кампании
1106        let previousLinksCount = 0;
1107        let stableCount = 0;
1108        const maxAttempts = 200; // Максимум попыток
1109        let attempts = 0;
1110        const scrollStep = 500; // Прокручиваем по 500px за раз
1111        
1112        while (attempts < maxAttempts) {
1113            // Собираем ссылки на текущем шаге
1114            const currentLinks = document.querySelectorAll('a[href*="/campaigns/auto-campaigns/"][href*="/campaign"]');
1115            currentLinks.forEach(link => {
1116                uniqueLinks.add(link.href);
1117            });
1118            
1119            const currentCount = uniqueLinks.size;
1120            console.log(`Загружено кампаний: ${currentCount}, прокрутка: ${tableContainer.scrollTop}/${tableContainer.scrollHeight}`);
1121            
1122            // Прокручиваем контейнер постепенно
1123            tableContainer.scrollTop += scrollStep;
1124            
1125            // Ждем загрузки новых элементов
1126            await wait(500);
1127            
1128            // Если количество не изменилось
1129            if (currentCount === previousLinksCount) {
1130                stableCount++;
1131                // Если количество стабильно 5 раз подряд - значит все загружено
1132                if (stableCount >= 5) {
1133                    console.log('Все кампании загружены');
1134                    break;
1135                }
1136            } else {
1137                stableCount = 0;
1138                previousLinksCount = currentCount;
1139            }
1140            
1141            // Если достигли конца контейнера
1142            if (tableContainer.scrollTop + tableContainer.clientHeight >= tableContainer.scrollHeight - 10) {
1143                console.log('Достигнут конец контейнера');
1144                // Ждем еще немного для загрузки последних элементов
1145                await wait(1000);
1146                
1147                // Собираем последние ссылки
1148                const finalLinks = document.querySelectorAll('a[href*="/campaigns/auto-campaigns/"][href*="/campaign"]');
1149                finalLinks.forEach(link => {
1150                    uniqueLinks.add(link.href);
1151                });
1152                
1153                // Проверяем еще раз количество
1154                if (uniqueLinks.size === previousLinksCount) {
1155                    break;
1156                }
1157                previousLinksCount = uniqueLinks.size;
1158            }
1159            
1160            attempts++;
1161        }
1162        
1163        // Преобразуем Set в массив URL (НЕ прокручиваем обратно!)
1164        const links = Array.from(uniqueLinks);
1165        
1166        console.log(`Найдено кампаний: ${links.length}`);
1167        console.log(`Всего попыток прокрутки: ${attempts}`);
1168        return links;
1169    }
1170
1171    // Старый метод прокрутки (fallback) - удален, больше не нужен
1172
1173    // Функция для массовой обработки кампаний
1174    async function runBulkStrategy() {
1175        if (isBulkProcessing) {
1176            showBulkStatus('Обработка уже выполняется', true);
1177            return;
1178        }
1179
1180        try {
1181            isBulkProcessing = true;
1182            console.log('Начало массовой обработки кампаний');
1183            
1184            bulkDesiredPercentage = parseFloat(document.getElementById('bulk-desired-percentage').value);
1185            if (!bulkDesiredPercentage || bulkDesiredPercentage <= 0) {
1186                showBulkStatus('Ошибка: введите корректный процент', true);
1187                isBulkProcessing = false;
1188                return;
1189            }
1190            console.log(`Желаемый процент: ${bulkDesiredPercentage}%`);
1191
1192            // Сохраняем ДРР для автоматической обработки
1193            await GM.setValue('bulkProcessingDRR', bulkDesiredPercentage);
1194            console.log(`ДРР ${bulkDesiredPercentage} сохранен для массовой обработки`);
1195
1196            // Прокручиваем страницу для загрузки всех кампаний
1197            const campaignLinks = await scrollToLoadAllCampaigns();
1198            
1199            if (campaignLinks.length === 0) {
1200                showBulkStatus('Ошибка: кампании не найдены', true);
1201                isBulkProcessing = false;
1202                await GM.deleteValue('bulkProcessingDRR');
1203                return;
1204            }
1205
1206            console.log(`Найдено кампаний для обработки: ${campaignLinks.length}`);
1207            showBulkStatus(`Начинаем обработку ${campaignLinks.length} кампаний...`);
1208            updateBulkProgress(0, campaignLinks.length);
1209
1210            // Сохраняем список кампаний (массив URL), текущий индекс и общее количество
1211            await GM.setValue('bulkCampaigns', JSON.stringify(campaignLinks));
1212            await GM.setValue('bulkCurrentIndex', 0);
1213            await GM.setValue('bulkTotalCampaigns', campaignLinks.length);
1214
1215            // Показываем кнопки управления
1216            const controlButtons = document.getElementById('bulk-control-buttons');
1217            if (controlButtons) {
1218                controlButtons.style.display = 'flex';
1219            }
1220
1221            // Открываем первую кампанию в новой вкладке через window.open
1222            if (campaignLinks.length > 0) {
1223                console.log(`Открытие кампании 1/${campaignLinks.length}: ${campaignLinks[0]}`);
1224                window.open(campaignLinks[0], '_blank');
1225            }
1226
1227        } catch (error) {
1228            console.error('Ошибка при массовой обработке:', error);
1229            showBulkStatus(`Ошибка: ${error.message}`, true);
1230            isBulkProcessing = false;
1231            await GM.deleteValue('bulkProcessingDRR');
1232        }
1233    }
1234
1235    // Функция для паузы массовой обработки
1236    async function pauseBulkProcessing() {
1237        bulkPaused = !bulkPaused;
1238        const pauseBtn = document.getElementById('pause-bulk-btn');
1239        
1240        if (bulkPaused) {
1241            await GM.setValue('bulkPaused', true);
1242            pauseBtn.textContent = '▶️ Продолжить';
1243            showBulkStatus('⏸️ Обработка приостановлена');
1244            console.log('Массовая обработка приостановлена');
1245        } else {
1246            await GM.deleteValue('bulkPaused');
1247            pauseBtn.textContent = '⏸️ Пауза';
1248            showBulkStatus('▶️ Обработка возобновлена');
1249            console.log('Массовая обработка возобновлена');
1250            
1251            // Продолжаем обработку - открываем следующую кампанию
1252            const campaignsJson = await GM.getValue('bulkCampaigns', null);
1253            const currentIndex = await GM.getValue('bulkCurrentIndex', 0);
1254            const totalCampaigns = await GM.getValue('bulkTotalCampaigns', 0);
1255            
1256            if (campaignsJson) {
1257                const campaigns = JSON.parse(campaignsJson);
1258                const nextIndex = currentIndex + 1;
1259                
1260                console.log(`Обработано кампаний: ${nextIndex} из ${totalCampaigns}`);
1261                
1262                if (nextIndex < campaigns.length) {
1263                    // Сохраняем новый индекс
1264                    await GM.setValue('bulkCurrentIndex', nextIndex);
1265                    
1266                    // Открываем следующую кампанию в новой вкладке через window.open
1267                    console.log(`Открываем кампанию ${nextIndex + 1}/${totalCampaigns}...`);
1268                    const newTab = window.open(campaigns[nextIndex], '_blank');
1269                    
1270                    if (newTab) {
1271                        // Закрываем текущую вкладку
1272                        await wait(1000);
1273                        window.close();
1274                    } else {
1275                        // Если блокировщик всплывающих окон, используем редирект
1276                        window.location.href = campaigns[nextIndex];
1277                    }
1278                }
1279            }
1280        }
1281    }
1282
1283    // Функция для остановки массовой обработки
1284    async function stopBulkProcessing() {
1285        await GM.deleteValue('bulkProcessingDRR');
1286        await GM.deleteValue('bulkCampaigns');
1287        await GM.deleteValue('bulkCurrentIndex');
1288        await GM.deleteValue('bulkPaused');
1289        
1290        showBulkStatus('⏹️ Обработка остановлена', true);
1291        console.log('Массовая обработка остановлена');
1292        
1293        // Скрываем кнопки управления
1294        const controlButtons = document.getElementById('bulk-control-buttons');
1295        if (controlButtons) {
1296            controlButtons.style.display = 'none';
1297        }
1298        
1299        isBulkProcessing = false;
1300        bulkPaused = false;
1301    }
1302
1303    // Функция для показа статуса
1304    function showStatus(message, isError = false) {
1305        const statusDiv = document.getElementById('status-message');
1306        if (statusDiv) {
1307            statusDiv.textContent = message;
1308            statusDiv.style.display = 'block';
1309            statusDiv.style.background = isError ? 'rgba(255, 59, 48, 0.9)' : 'rgba(52, 199, 89, 0.9)';
1310            console.log(`Статус: ${message}`);
1311        }
1312    }
1313
1314    // Функция для ожидания
1315    function wait(ms) {
1316        return new Promise(resolve => setTimeout(resolve, ms));
1317    }
1318
1319    // Функция для парсинга числа из строки
1320    function parseNumber(str) {
1321        if (!str) return 0;
1322        // Убираем все символы кроме цифр, точек и запятых
1323        const cleaned = str.replace(/[^\d.,]/g, '').replace(/\s/g, '');
1324        // Заменяем запятую на точку
1325        const normalized = cleaned.replace(',', '.');
1326        return parseFloat(normalized) || 0;
1327    }
1328
1329    // Функция для парсинга процента
1330    function parsePercentage(str) {
1331        if (!str) return 0;
1332        const cleaned = str.replace('%', '').replace(',', '.').trim();
1333        return parseFloat(cleaned) || 0;
1334    }
1335
1336    // Основная функция запуска стратегии
1337    async function runStrategy() {
1338        try {
1339            console.log('Начало выполнения стратегии');
1340            showStatus('Запуск процесса...');
1341
1342            const desiredPercentage = parseFloat(document.getElementById('desired-percentage').value);
1343            if (!desiredPercentage || desiredPercentage <= 0) {
1344                showStatus('Ошибка: введите корректный процент', true);
1345                await handleStrategyError();
1346                return;
1347            }
1348            console.log(`Желаемый процент: ${desiredPercentage}%`);
1349
1350            // Шаг 1: Кликаем на статистику
1351            showStatus('Открытие статистики...');
1352            const statsButton = document.querySelector('.css-amj7dw');
1353            if (!statsButton) {
1354                showStatus('Ошибка: кнопка статистики не найдена', true);
1355                await handleStrategyError();
1356                return;
1357            }
1358            statsButton.click();
1359            console.log('Клик на статистику выполнен');
1360            await wait(2000); // Увеличена задержка для загрузки статистики
1361
1362            // Шаг 1.5: Выбираем режим "Товары"
1363            showStatus('Выбор режима "Товары"...');
1364            const modeLabels = Array.from(document.querySelectorAll('label'));
1365            let modeInput = null;
1366            
1367            for (const label of modeLabels) {
1368                if (label.textContent.trim() === 'Режим') {
1369                    const inputId = label.getAttribute('for');
1370                    if (inputId) {
1371                        modeInput = document.getElementById(inputId);
1372                        console.log(`Найдено поле Режим с id: ${inputId}`);
1373                        break;
1374                    }
1375                }
1376            }
1377            
1378            if (modeInput) {
1379                // Устанавливаем значение "Товары" напрямую
1380                modeInput.value = 'Товары';
1381                
1382                // Триггерим события для React
1383                const inputEvent = new Event('input', { bubbles: true });
1384                const changeEvent = new Event('change', { bubbles: true });
1385                modeInput.dispatchEvent(inputEvent);
1386                modeInput.dispatchEvent(changeEvent);
1387                
1388                console.log('Установлено значение: Товары');
1389                await wait(1000); // Увеличена задержка для загрузки опций
1390                
1391                // Проверяем, появились ли опции в выпадающем списке
1392                const options = document.querySelectorAll('[role="option"]');
1393                console.log(`Найдено опций: ${options.length}`);
1394                
1395                if (options.length > 0) {
1396                    // Ищем опцию "Товары" и кликаем на неё
1397                    const tovarOption = Array.from(options).find(opt => opt.textContent.includes('Товары'));
1398                    if (tovarOption) {
1399                        tovarOption.click();
1400                        console.log('Выбран режим "Товары"');
1401                        await wait(1000); // Увеличена задержка для загрузки данных после выбора режима
1402                    }
1403                }
1404            }
1405
1406            // Шаг 2: Извлекаем данные из статистики
1407            showStatus('Извлечение данных...');
1408            
1409            // Ждем дополнительное время для загрузки статистики
1410            await wait(500);
1411            
1412            const stats = Array.from(document.querySelectorAll('.MuiTypography-caption.css-1et52kr'));
1413            
1414            let sumOrders = 0;
1415            let ordersCount = 0;
1416            let cartToOrderPercent = 0;
1417
1418            stats.forEach(el => {
1419                const text = el.textContent.trim();
1420                const valueElement = el.closest('.MuiBox-root')?.querySelector('.MuiTypography-h3 .MuiTypography-body1');
1421                const value = valueElement ? valueElement.textContent.trim() : '';
1422
1423                console.log(`Найден показатель: ${text} = ${value}`);
1424
1425                if (text === 'Сумма заказов') {
1426                    sumOrders = parseNumber(value);
1427                    console.log(`Сумма заказов: ${sumOrders}`);
1428                } else if (text === 'Заказов') {
1429                    ordersCount = parseNumber(value);
1430                    console.log(`Заказов: ${ordersCount}`);
1431                } else if (text === 'Корзина → Заказ') {
1432                    cartToOrderPercent = parsePercentage(value);
1433                    console.log(`Корзина → Заказ: ${cartToOrderPercent}%`);
1434                }
1435            });
1436
1437            if (sumOrders === 0 || ordersCount === 0 || cartToOrderPercent === 0) {
1438                showStatus('Ошибка: не удалось получить данные статистики', true);
1439                console.error('Недостаточно данных:', { sumOrders, ordersCount, cartToOrderPercent });
1440                await handleStrategyError();
1441                return;
1442            }
1443
1444            // Шаг 3: Вычисляем стоимость корзины
1445            const cartCost = (sumOrders / ordersCount) * (desiredPercentage / 100) * (cartToOrderPercent / 100);
1446            const cartCostRounded = Math.round(cartCost * 100) / 100;
1447            console.log(`Расчет: (${sumOrders} / ${ordersCount}) * (${desiredPercentage} / 100) * (${cartToOrderPercent} / 100) = ${cartCostRounded}`);
1448            showStatus(`Рассчитано: ${cartCostRounded}`);
1449
1450            // Закрываем статистику
1451            statsButton.click();
1452            await wait(500);
1453
1454            // Шаг 4: Кликаем на "Вставить стратегию"
1455            showStatus('Вставка стратегии...');
1456            const insertButtons = document.querySelectorAll('.css-5kbhos');
1457            let insertButton = null;
1458            
1459            // Ищем кнопку с текстом "Вставить стратегию"
1460            for (const btn of insertButtons) {
1461                if (btn.textContent.includes('Вставить стратегию')) {
1462                    insertButton = btn;
1463                    break;
1464                }
1465            }
1466
1467            if (!insertButton && insertButtons.length >= 2) {
1468                insertButton = insertButtons[1];
1469            } else if (!insertButton && insertButtons.length === 1) {
1470                insertButton = insertButtons[0];
1471            }
1472
1473            if (!insertButton) {
1474                showStatus('Ошибка: кнопка "Вставить стратегию" не найдена', true);
1475                await handleStrategyError();
1476                return;
1477            }
1478
1479            // Получаем текущую выбранную стратегию
1480            const currentStrategyCode = await getCurrentStrategy();
1481            console.log('Используем стратегию, длина:', currentStrategyCode.length);
1482            console.log('Первые 50 символов стратегии:', currentStrategyCode.substring(0, 50));
1483            console.log('Последние 50 символов стратегии:', currentStrategyCode.substring(currentStrategyCode.length - 50));
1484            
1485            // Копируем код стратегии в буфер обмена ПЕРЕД открытием модального окна
1486            console.log('Копируем стратегию в буфер обмена...');
1487            
1488            // Пробуем несколько способов копирования
1489            try {
1490                // Способ 1: navigator.clipboard (современный)
1491                await navigator.clipboard.writeText(currentStrategyCode);
1492                console.log('✓ Стратегия скопирована через navigator.clipboard');
1493            } catch (e) {
1494                console.log('navigator.clipboard не сработал:', e.message);
1495                console.log('Пробуем GM.setClipboard...');
1496                // Способ 2: GM.setClipboard (fallback)
1497                try {
1498                    await GM.setClipboard(currentStrategyCode);
1499                    console.log('✓ Стратегия скопирована через GM.setClipboard');
1500                } catch (e2) {
1501                    console.error('Ошибка копирования через GM.setClipboard:', e2.message);
1502                }
1503            }
1504            
1505            console.log('Длина стратегии:', currentStrategyCode.length);
1506            await wait(500);
1507
1508            insertButton.click();
1509            console.log('Клик на "Вставить стратегию" выполнен');
1510            await wait(500); // Увеличена задержка для применения стратегии из буфера
1511            
1512            console.log('✓ Стратегия вставлена из буфера обмена');
1513            
1514            await wait(500);
1515
1516            // Шаг 5: Находим поле "Желаемое значение" и вставляем результат
1517            showStatus('Заполнение поля...');
1518            
1519            // Ищем поле с текстом "За корзину" или "Желаемое значение"
1520            const inputLabels = Array.from(document.querySelectorAll('.MuiInputLabel-root'));
1521            let targetInput = null;
1522
1523            for (const label of inputLabels) {
1524                const labelText = label.textContent;
1525                if (labelText.includes('Желаемое значение За корзину')) {
1526                    const inputId = label.getAttribute('for');
1527                    if (inputId) {
1528                        targetInput = document.getElementById(inputId);
1529                        console.log(`Найдено поле: ${labelText}, id: ${inputId}`);
1530                        break;
1531                    }
1532                }
1533            }
1534
1535            // Если не нашли по лейблу, ищем по имени
1536            if (!targetInput) {
1537                const inputs = document.querySelectorAll('input[type="number"]');
1538                for (const input of inputs) {
1539                    const name = input.getAttribute('name') || '';
1540                    if (name.includes('rules') && name.includes('value')) {
1541                        targetInput = input;
1542                        console.log(`Найдено поле по имени: ${name}`);
1543                        break;
1544                    }
1545                }
1546            }
1547
1548            if (!targetInput) {
1549                showStatus('Ошибка: поле для ввода не найдено', true);
1550                console.error('Не удалось найти поле для ввода значения');
1551                await handleStrategyError();
1552                return;
1553            }
1554
1555            // Устанавливаем значение
1556            targetInput.focus();
1557            targetInput.value = cartCostRounded.toString();
1558            
1559            // Триггерим события для React
1560            const inputEvent = new Event('input', { bubbles: true });
1561            const changeEvent = new Event('change', { bubbles: true });
1562            targetInput.dispatchEvent(inputEvent);
1563            targetInput.dispatchEvent(changeEvent);
1564            
1565            console.log(`Значение ${cartCostRounded} установлено в поле ${targetInput.id}`);
1566            await wait(500);
1567
1568            // Шаг 7: Нажимаем "Сохранить"
1569            showStatus('Сохранение...');
1570            const saveButtons = document.querySelectorAll('button');
1571            let saveButton = null;
1572
1573            for (const btn of saveButtons) {
1574                if (btn.textContent.trim() === 'Сохранить') {
1575                    saveButton = btn;
1576                    break;
1577                }
1578            }
1579
1580            if (!saveButton) {
1581                showStatus('Ошибка: кнопка "Сохранить" не найдена', true);
1582                await handleStrategyError();
1583                return;
1584            }
1585
1586            saveButton.click();
1587            console.log('Клик на "Сохранить" выполнен');
1588            await wait(500);
1589
1590            showStatus(`✅ Готово! Стоимость корзины: ${cartCostRounded}`);
1591            console.log('Стратегия успешно установлена');
1592
1593            // Шаг 8: Работа с кластерами (только если чекбокс включен)
1594            const applyToClusters = document.getElementById('apply-to-clusters');
1595            const shouldApplyToClusters = applyToClusters ? applyToClusters.checked : true;
1596            
1597            if (!shouldApplyToClusters) {
1598                console.log('Применение стратегии к кластерам отключено');
1599                showStatus('✅ Готово! Кластеры пропущены');
1600            } else {
1601                console.log('Применение стратегии к кластерам включено');
1602                
1603                // 8.1: Переходим во вкладку "Кластеры"
1604                const tabs = Array.from(document.querySelectorAll('button[role="tab"]'));
1605                const clustersTab = tabs.find(tab => tab.textContent.trim() === 'Кластеры');
1606                if (!clustersTab) {
1607                    console.error('Вкладка "Кластеры" не найдена');
1608                    showStatus('⚠️ Вкладка "Кластеры" не найдена, пропускаем', true);
1609                } else {
1610                    clustersTab.click();
1611                    console.log('Клик на вкладку "Кластеры" выполнен');
1612                    await wait(1000); // Увеличена задержка для загрузки кластеров
1613                    
1614                    // Ждем, пока исчезнет скелетон загрузки
1615                    let loadingAttempts = 0;
1616                    while (loadingAttempts < 10) {
1617                        const skeleton = document.querySelector('.MuiSkeleton-root');
1618                        if (!skeleton) {
1619                            console.log('Кластеры загружены');
1620                            break;
1621                        }
1622                        console.log(`Ожидание загрузки кластеров, попытка ${loadingAttempts + 1}`);
1623                        await wait(500);
1624                        loadingAttempts++;
1625                    }
1626                    
1627                    // 8.2: Выделяем все кластеры - клик в checkbox
1628                    showStatus('Выделение всех кластеров...');
1629                    let selectAllCheckbox = null;
1630                    
1631                    // Способ 1: Ищем через контейнер css-1ytbthu
1632                    const checkboxContainer = document.querySelector('.css-1ytbthu');
1633                    if (checkboxContainer) {
1634                        selectAllCheckbox = checkboxContainer.querySelector('.css-vlug8u');
1635                        console.log('Найден checkbox через контейнер css-1ytbthu');
1636                    }
1637                    
1638                    // Способ 2: Ищем напрямую по классу vlug8u в заголовке таблицы
1639                    if (!selectAllCheckbox) {
1640                        const tableHeader = document.querySelector('thead');
1641                        if (tableHeader) {
1642                            selectAllCheckbox = tableHeader.querySelector('.css-vlug8u');
1643                            console.log('Найден checkbox в заголовке таблицы');
1644                        }
1645                    }
1646                    
1647                    // Способ 3: Ищем первый checkbox в таблице
1648                    if (!selectAllCheckbox) {
1649                        const checkboxes = document.querySelectorAll('input[type="checkbox"]');
1650                        if (checkboxes.length > 0) {
1651                            selectAllCheckbox = checkboxes[0];
1652                            console.log('Найден checkbox через input[type="checkbox"]');
1653                        }
1654                    }
1655                    
1656                    if (!selectAllCheckbox) {
1657                        console.error('Checkbox для выделения всех кластеров не найден');
1658                        showStatus('⚠️ Checkbox не найден, пропускаем кластеры', true);
1659                    } else {
1660                        selectAllCheckbox.click();
1661                        console.log('Все кластеры выделены');
1662                        await wait(500);
1663                        
1664                        // 8.3: Кликаем на "Действия"
1665                        showStatus('Открытие меню действий...');
1666                        const actionsButton = document.querySelector('.css-1rll63h');
1667                        if (!actionsButton) {
1668                            console.error('Кнопка "Действия" не найдена');
1669                            showStatus('⚠️ Кнопка "Действия" не найдена', true);
1670                        } else {
1671                            actionsButton.click();
1672                            console.log('Клик на "Действия" выполнен');
1673                            await wait(500);
1674                            
1675                            // 8.4: Кликаем на "Управление" - второй элемент с классом hq58ok
1676                            showStatus('Открытие управления...');
1677                            const managementButtons = document.querySelectorAll('.css-hq58ok');
1678                            if (managementButtons.length < 2) {
1679                                console.error('Кнопка "Управление" не найдена');
1680                                showStatus('⚠️ Кнопка "Управление" не найдена', true);
1681                            } else {
1682                                managementButtons[1].click();
1683                                console.log('Клик на "Управление" выполнен');
1684                                await wait(500);
1685                                
1686                                // 8.5: Кликаем на "Стратегия" - 3-й элемент с классом css-582wun
1687                                showStatus('Открытие стратегии кластеров...');
1688                                const strategyTabs = document.querySelectorAll('.css-582wun');
1689                                if (strategyTabs.length < 3) {
1690                                    console.error('Вкладка "Стратегия" не найдена');
1691                                    showStatus('⚠️ Вкладка "Стратегия" не найдена', true);
1692                                } else {
1693                                    strategyTabs[2].click();
1694                                    console.log('Клик на "Стратегия" выполнен');
1695                                    await wait(500);
1696                                    
1697                                    // 8.6: Вставляем стратегию и рассчитанную ставку
1698                                    showStatus('Вставка стратегии для кластеров...');
1699                                    const clusterInsertButtons = document.querySelectorAll('.css-5kbhos');
1700                                    let clusterInsertButton = null;
1701                                    
1702                                    for (const btn of clusterInsertButtons) {
1703                                        if (btn.textContent.includes('Вставить стратегию')) {
1704                                            clusterInsertButton = btn;
1705                                            break;
1706                                        }
1707                                    }
1708                                    
1709                                    if (!clusterInsertButton && clusterInsertButtons.length > 0) {
1710                                        clusterInsertButton = clusterInsertButtons[0];
1711                                    }
1712                                    
1713                                    if (!clusterInsertButton) {
1714                                        console.error('Кнопка "Вставить стратегию" для кластеров не найдена');
1715                                        showStatus('⚠️ Кнопка вставки стратегии не найдена', true);
1716                                    } else {
1717                                        // Получаем текущую кластерную стратегию и копируем в буфер
1718                                        const currentClusterStrategyCode = await getCurrentClusterStrategy();
1719                                        console.log('Используем кластерную стратегию, длина:', currentClusterStrategyCode.length);
1720                                        console.log('Первые 50 символов кластерной стратегии:', currentClusterStrategyCode.substring(0, 50));
1721                                        console.log('Последние 50 символов кластерной стратегии:', currentClusterStrategyCode.substring(currentClusterStrategyCode.length - 50));
1722                                        
1723                                        // Копируем код стратегии в буфер обмена
1724                                        console.log('Копируем кластерную стратегию в буфер обмена...');
1725                                        
1726                                        // Пробуем несколько способов копирования
1727                                        try {
1728                                            // Способ 1: navigator.clipboard (современный)
1729                                            await navigator.clipboard.writeText(currentClusterStrategyCode);
1730                                            console.log('✓ Кластерная стратегия скопирована через navigator.clipboard');
1731                                        } catch (e) {
1732                                            console.log('navigator.clipboard не сработал, пробуем GM.setClipboard...');
1733                                            // Способ 2: GM.setClipboard (fallback)
1734                                            await GM.setClipboard(currentClusterStrategyCode);
1735                                            console.log('✓ Кластерная стратегия скопирована через GM.setClipboard');
1736                                        }
1737                                        
1738                                        console.log('Длина кластерной стратегии:', currentClusterStrategyCode.length);
1739                                        await wait(500);
1740                                        
1741                                        clusterInsertButton.click();
1742                                        console.log('Клик на "Вставить стратегию" для кластеров выполнен');
1743                                        await wait(1000);
1744                                        
1745                                        // Находим поле для ввода ставки за корзину
1746                                        const clusterInputLabels = Array.from(document.querySelectorAll('.MuiInputLabel-root'));
1747                                        let clusterTargetInput = null;
1748                                        
1749                                        for (const label of clusterInputLabels) {
1750                                            const labelText = label.textContent;
1751                                            if (labelText.includes('Желаемое значение За корзину')) {
1752                                                const inputId = label.getAttribute('for');
1753                                                if (inputId) {
1754                                                    clusterTargetInput = document.getElementById(inputId);
1755                                                    console.log(`Найдено поле для кластеров: ${labelText}`);
1756                                                    break;
1757                                                }
1758                                            }
1759                                        }
1760                                        
1761                                        if (!clusterTargetInput) {
1762                                            const clusterInputs = document.querySelectorAll('input[type="number"]');
1763                                            for (const input of clusterInputs) {
1764                                                const name = input.getAttribute('name') || '';
1765                                                if (name.includes('CostPerAddedToCart') || name.includes('value')) {
1766                                                    clusterTargetInput = input;
1767                                                    console.log(`Найдено поле по имени: ${name}`);
1768                                                    break;
1769                                                }
1770                                            }
1771                                        }
1772                                        
1773                                        if (clusterTargetInput) {
1774                                            clusterTargetInput.focus();
1775                                            clusterTargetInput.value = cartCostRounded.toString();
1776                                            
1777                                            const inputEvent = new Event('input', { bubbles: true });
1778                                            const changeEvent = new Event('change', { bubbles: true });
1779                                            clusterTargetInput.dispatchEvent(inputEvent);
1780                                            clusterTargetInput.dispatchEvent(changeEvent);
1781                                            
1782                                            console.log(`Значение ${cartCostRounded} установлено для кластеров`);
1783                                            await wait(500);
1784                                        }
1785                                        
1786                                        // Нажимаем "Применить" после вставки стратегии - 2-й элемент с классом css-eqlbov
1787                                        showStatus('Применение стратегии кластеров...');
1788                                        const clusterStrategyApplyButtons = document.querySelectorAll('.css-eqlbov');
1789                                        if (clusterStrategyApplyButtons.length < 2) {
1790                                            console.error('Кнопка "Применить" стратегию для кластеров не найдена');
1791                                            showStatus('⚠️ Кнопка "Применить" стратегию не найдена', true);
1792                                        } else {
1793                                            clusterStrategyApplyButtons[1].click();
1794                                            console.log('Клик на "Применить" стратегию для кластеров выполнен');
1795                                            await wait(1000);
1796                                            
1797                                            // 8.7: Закрываем модальное окно управления кластерами (если оно открыто)
1798                                            // Ищем кнопку закрытия модального окна
1799                                            const closeModalButtons = document.querySelectorAll('button[aria-label="Close"]');
1800                                            if (closeModalButtons.length > 0) {
1801                                                closeModalButtons[closeModalButtons.length - 1].click();
1802                                                console.log('Модальное окно управления закрыто');
1803                                                await wait(1000);
1804                                            }
1805                                            
1806                                            // 8.8: Работаем с аккордеоном "Автофильтры" на странице кластеров
1807                                            showStatus('Открытие автофильтров...');
1808                                            
1809                                            // Ищем аккордеон "Автофильтры" по ID
1810                                            const autofilterAccordion = document.getElementById('bidder-constructor');
1811                                            if (!autofilterAccordion) {
1812                                                console.error('Аккордеон "Автофильтры" не найден');
1813                                                showStatus('⚠️ Аккордеон "Автофильтры" не найден', true);
1814                                            } else {
1815                                                // Проверяем, раскрыт ли аккордеон
1816                                                const accordionButton = autofilterAccordion.querySelector('button[aria-expanded]');
1817                                                const isExpanded = accordionButton && accordionButton.getAttribute('aria-expanded') === 'true';
1818                                                
1819                                                if (!isExpanded && accordionButton) {
1820                                                    // Раскрываем аккордеон
1821                                                    accordionButton.click();
1822                                                    console.log('Аккордеон "Автофильтры" раскрыт');
1823                                                    await wait(1000);
1824                                                } else {
1825                                                    console.log('Аккордеон "Автофильтры" уже раскрыт');
1826                                                }
1827                                                
1828                                                // 8.9: Кликаем на "Шаблоны" внутри аккордеона
1829                                                showStatus('Открытие шаблонов...');
1830                                                
1831                                                // Ищем кнопку "Шаблоны" внутри аккордеона
1832                                                const templatesButtons = autofilterAccordion.querySelectorAll('button');
1833                                                let templateButton = null;
1834                                                
1835                                                for (const btn of templatesButtons) {
1836                                                    if (btn.textContent.trim() === 'Шаблоны') {
1837                                                        templateButton = btn;
1838                                                        console.log('Найдена кнопка "Шаблоны" в аккордеоне');
1839                                                        break;
1840                                                    }
1841                                                }
1842                                                
1843                                                if (!templateButton) {
1844                                                    console.error('Кнопка "Шаблоны" не найдена в аккордеоне');
1845                                                    showStatus('⚠️ Кнопка "Шаблоны" не найдена', true);
1846                                                } else {
1847                                                    templateButton.click();
1848                                                    console.log('Клик на "Шаблоны" выполнен');
1849                                                    await wait(500);
1850                                                    
1851                                                    // 8.10: Выбираем "Расширение"
1852                                                    showStatus('Выбор шаблона "Расширение"...');
1853                                                    
1854                                                    // Ищем элемент с текстом "Расширение"
1855                                                    const allElements = document.querySelectorAll('div, button, span, p');
1856                                                    let extensionTemplate = null;
1857                                                    
1858                                                    for (const el of allElements) {
1859                                                        const text = el.textContent.trim();
1860                                                        if (text === 'Расширение') {
1861                                                            extensionTemplate = el;
1862                                                            console.log(`Найден шаблон "Расширение", элемент: ${el.tagName}, класс: ${el.className}`);
1863                                                            break;
1864                                                        }
1865                                                    }
1866                                                    
1867                                                    if (!extensionTemplate) {
1868                                                        console.error('Шаблон "Расширение" не найден');
1869                                                        console.log('Доступные элементы после клика на Шаблоны:');
1870                                                        const allVisible = document.querySelectorAll('div, button, span, p');
1871                                                        allVisible.forEach((el, i) => {
1872                                                            if (i < 20) {
1873                                                                console.log(`Элемент ${i}: ${el.tagName}, текст: ${el.textContent.substring(0, 30)}`);
1874                                                            }
1875                                                        });
1876                                                        showStatus('⚠️ Шаблон "Расширение" не найден', true);
1877                                                    } else {
1878                                                        extensionTemplate.click();
1879                                                        console.log('Шаблон "Расширение" выбран');
1880                                                        await wait(500);
1881                                                        
1882                                                        // 8.11: Кликаем на "Сохранить"
1883                                                        showStatus('Сохранение автофильтров...');
1884                                                        
1885                                                        const saveButtonsAfterTemplate = document.querySelectorAll('button');
1886                                                        let saveAutofilterButton = null;
1887                                                        
1888                                                        for (const btn of saveButtonsAfterTemplate) {
1889                                                            if (btn.textContent.trim() === 'Сохранить') {
1890                                                                saveAutofilterButton = btn;
1891                                                                console.log('Найдена кнопка "Сохранить" для автофильтров');
1892                                                                break;
1893                                                            }
1894                                                        }
1895                                                        
1896                                                        if (!saveAutofilterButton) {
1897                                                            console.error('Кнопка "Сохранить" для автофильтров не найдена');
1898                                                            showStatus('⚠️ Кнопка "Сохранить" не найдена', true);
1899                                                        } else {
1900                                                            saveAutofilterButton.click();
1901                                                            console.log('Клик на "Сохранить" автофильтры выполнен');
1902                                                            await wait(1000);
1903                                                            
1904                                                            // 8.12: Кликаем на "Применить автофильтры вручную"
1905                                                            showStatus('Применение автофильтров вручную...');
1906                                                            
1907                                                            const applyButtonsAfterSave = document.querySelectorAll('button');
1908                                                            let applyAutofilterButton = null;
1909                                                            
1910                                                            for (const btn of applyButtonsAfterSave) {
1911                                                                if (btn.textContent.trim() === 'Применить автофильтры вручную') {
1912                                                                    applyAutofilterButton = btn;
1913                                                                    console.log('Найдена кнопка "Применить автофильтры вручную"');
1914                                                                    break;
1915                                                                }
1916                                                            }
1917                                                            
1918                                                            if (!applyAutofilterButton) {
1919                                                                console.error('Кнопка "Применить автофильтры вручную" не найдена');
1920                                                                showStatus('⚠️ Кнопка "Применить автофильтры вручную" не найдена', true);
1921                                                            } else {
1922                                                                applyAutofilterButton.click();
1923                                                                console.log('Клик на "Применить автофильтры вручную" выполнен');
1924                                                                await wait(1000);
1925                                                            }
1926                                                        }
1927                                                    }
1928                                                }
1929                                            }
1930                                        }
1931                                    }
1932                                }
1933                            }
1934                        }
1935                    }
1936                }
1937            }
1938
1939            showStatus(`✅ Полностью готово! Стоимость корзины: ${cartCostRounded}`);
1940            console.log('Стратегия и кластеры успешно настроены');
1941
1942            // Проверяем, есть ли массовая обработка
1943            const savedDRR = await GM.getValue('bulkProcessingDRR', null);
1944            if (savedDRR !== null) {
1945                console.log('Обнаружена массовая обработка, переходим к следующей кампании');
1946                
1947                // Проверяем, не на паузе ли обработка
1948                const isPaused = await GM.getValue('bulkPaused', false);
1949                if (isPaused) {
1950                    console.log('Обработка на паузе, ждем возобновления');
1951                    showStatus('⏸️ Обработка на паузе');
1952                    return;
1953                }
1954                
1955                // Получаем список кампаний, текущий индекс и общее количество
1956                const campaignsJson = await GM.getValue('bulkCampaigns', null);
1957                const currentIndex = await GM.getValue('bulkCurrentIndex', 0);
1958                const totalCampaigns = await GM.getValue('bulkTotalCampaigns', 0);
1959                
1960                if (campaignsJson) {
1961                    const campaigns = JSON.parse(campaignsJson);
1962                    const nextIndex = currentIndex + 1;
1963                    
1964                    console.log(`Обработано кампаний: ${nextIndex} из ${totalCampaigns}`);
1965                    
1966                    if (nextIndex < campaigns.length) {
1967                        // Сохраняем новый индекс
1968                        await GM.setValue('bulkCurrentIndex', nextIndex);
1969                        
1970                        // Открываем следующую кампанию в новой вкладке через window.open
1971                        console.log(`Открываем кампанию ${nextIndex + 1}/${totalCampaigns}...`);
1972                        const newTab = window.open(campaigns[nextIndex], '_blank');
1973                        
1974                        if (newTab) {
1975                            // Закрываем текущую вкладку
1976                            await wait(1000);
1977                            window.close();
1978                        } else {
1979                            // Если блокировщик всплывающих окон, используем редирект
1980                            console.log('Блокировщик всплывающих окон, используем редирект');
1981                            window.location.href = campaigns[nextIndex];
1982                        }
1983                    } else {
1984                        // Все кампании обработаны
1985                        console.log('✅ Все кампании обработаны!');
1986                        await GM.deleteValue('bulkProcessingDRR');
1987                        await GM.deleteValue('bulkCampaigns');
1988                        await GM.deleteValue('bulkCurrentIndex');
1989                        await GM.deleteValue('bulkTotalCampaigns');
1990                        
1991                        // Закрываем текущую вкладку
1992                        showStatus('✅ Все кампании обработаны! Закрытие вкладки...');
1993                        await wait(1000);
1994                        window.close();
1995                    }
1996                }
1997            }
1998
1999        } catch (error) {
2000            console.error('Ошибка при выполнении стратегии:', error);
2001            showStatus(`Ошибка: ${error.message}`, true);
2002            await handleStrategyError();
2003        }
2004    }
2005
2006    // Функция для обработки ошибок и перехода к следующей кампании
2007    async function handleStrategyError() {
2008        const savedDRR = await GM.getValue('bulkProcessingDRR', null);
2009        if (savedDRR !== null) {
2010            console.log('Обнаружена ошибка при массовой обработке, ждем 10 секунд перед переходом к следующей кампании');
2011            showStatus('⚠️ Ошибка! Переход к следующей кампании через 10 секунд...', true);
2012            
2013            // Ждем 10 секунд
2014            for (let i = 10; i > 0; i--) {
2015                showStatus(`⚠️ Ошибка! Переход к следующей через ${i} сек...`, true);
2016                await wait(1000);
2017            }
2018            
2019            // Получаем список кампаний и текущий индекс
2020            const campaignsJson = await GM.getValue('bulkCampaigns', null);
2021            const currentIndex = await GM.getValue('bulkCurrentIndex', 0);
2022            
2023            if (campaignsJson) {
2024                const campaigns = JSON.parse(campaignsJson);
2025                const nextIndex = currentIndex + 1;
2026                
2027                console.log(`Пропускаем кампанию с ошибкой. Переход к ${nextIndex + 1} из ${campaigns.length}`);
2028                
2029                if (nextIndex < campaigns.length) {
2030                    // Сохраняем новый индекс
2031                    await GM.setValue('bulkCurrentIndex', nextIndex);
2032                    
2033                    // Открываем следующую кампанию в новой вкладке через window.open
2034                    console.log(`Открытие кампании ${nextIndex + 1}: ${campaigns[nextIndex]}`);
2035                    const newTab = window.open(campaigns[nextIndex], '_blank');
2036                    
2037                    if (newTab) {
2038                        // Закрываем текущую вкладку
2039                        await wait(1000);
2040                        window.close();
2041                    } else {
2042                        // Если блокировщик всплывающих окон, используем редирект
2043                        window.location.href = campaigns[nextIndex];
2044                    }
2045                } else {
2046                    // Все кампании обработаны
2047                    console.log('Все кампании обработаны, очищаем данные');
2048                    await GM.deleteValue('bulkProcessingDRR');
2049                    await GM.deleteValue('bulkCampaigns');
2050                    await GM.deleteValue('bulkCurrentIndex');
2051                    await GM.deleteValue('bulkTotalCampaigns');
2052                    
2053                    // Закрываем текущую вкладку
2054                    showStatus('✅ Все кампании обработаны! Закрытие вкладки...');
2055                    await wait(1000);
2056                    window.close();
2057                }
2058            }
2059        }
2060    }
2061
2062    // Инициализация
2063    function init() {
2064        console.log('Инициализация расширения');
2065        
2066        // Проверяем, на какой странице мы находимся
2067        if (window.location.href.includes('/advert/campaigns')) {
2068            // Страница со списком кампаний
2069            console.log('Страница списка кампаний обнаружена');
2070            
2071            setTimeout(() => {
2072                if (document.body) {
2073                    createBulkUI();
2074                } else {
2075                    console.error('Body не найден');
2076                }
2077            }, 1000);
2078        } else if (window.location.href.includes('/campaigns/auto-campaigns/') && window.location.href.includes('/campaign')) {
2079            // Страница отдельной кампании
2080            console.log('Страница кампании обнаружена');
2081            
2082            // Создаем UI с небольшой задержкой, чтобы убедиться, что страница загружена
2083            setTimeout(() => {
2084                if (document.body) {
2085                    createUI();
2086                } else {
2087                    console.error('Body не найден');
2088                }
2089            }, 1000);
2090        } else {
2091            console.log('Не на странице кампании, UI не создается');
2092        }
2093    }
2094
2095    // Запускаем инициализацию
2096    init();
2097
2098})();