MP Manager Auto Strategy Setter

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

Size

103.6 KB

Version

1.8.27

Created

Feb 10, 2026

Updated

about 1 month ago

1// ==UserScript==
2// @name		MP Manager Auto Strategy Setter
3// @description		Автоматическая установка стратегии рекламной кампании на основе статистики
4// @version		1.8.27
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 = 50;
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="50" 
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="50" 
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
1214            // Показываем кнопки управления
1215            const controlButtons = document.getElementById('bulk-control-buttons');
1216            if (controlButtons) {
1217                controlButtons.style.display = 'flex';
1218            }
1219
1220            // Открываем первую кампанию в новой вкладке
1221            if (campaignLinks.length > 0) {
1222                console.log(`Открытие кампании: ${campaignLinks[0]}`);
1223                await GM.openInTab(campaignLinks[0], false);
1224            }
1225
1226        } catch (error) {
1227            console.error('Ошибка при массовой обработке:', error);
1228            showBulkStatus(`Ошибка: ${error.message}`, true);
1229            isBulkProcessing = false;
1230            await GM.deleteValue('bulkProcessingDRR');
1231        }
1232    }
1233
1234    // Функция для паузы массовой обработки
1235    async function pauseBulkProcessing() {
1236        bulkPaused = !bulkPaused;
1237        const pauseBtn = document.getElementById('pause-bulk-btn');
1238        
1239        if (bulkPaused) {
1240            await GM.setValue('bulkPaused', true);
1241            pauseBtn.textContent = '▶️ Продолжить';
1242            showBulkStatus('⏸️ Обработка приостановлена');
1243            console.log('Массовая обработка приостановлена');
1244        } else {
1245            await GM.deleteValue('bulkPaused');
1246            pauseBtn.textContent = '⏸️ Пауза';
1247            showBulkStatus('▶️ Обработка возобновлена');
1248            console.log('Массовая обработка возобновлена');
1249            
1250            // Продолжаем обработку - открываем следующую кампанию
1251            const campaignsJson = await GM.getValue('bulkCampaigns', null);
1252            const currentIndex = await GM.getValue('bulkCurrentIndex', 0);
1253            
1254            if (campaignsJson) {
1255                const campaigns = JSON.parse(campaignsJson);
1256                if (currentIndex < campaigns.length) {
1257                    console.log(`Продолжение с кампании ${currentIndex + 1}: ${campaigns[currentIndex]}`);
1258                    await GM.openInTab(campaigns[currentIndex], false);
1259                }
1260            }
1261        }
1262    }
1263
1264    // Функция для остановки массовой обработки
1265    async function stopBulkProcessing() {
1266        await GM.deleteValue('bulkProcessingDRR');
1267        await GM.deleteValue('bulkCampaigns');
1268        await GM.deleteValue('bulkCurrentIndex');
1269        await GM.deleteValue('bulkPaused');
1270        
1271        showBulkStatus('⏹️ Обработка остановлена', true);
1272        console.log('Массовая обработка остановлена');
1273        
1274        // Скрываем кнопки управления
1275        const controlButtons = document.getElementById('bulk-control-buttons');
1276        if (controlButtons) {
1277            controlButtons.style.display = 'none';
1278        }
1279        
1280        isBulkProcessing = false;
1281        bulkPaused = false;
1282    }
1283
1284    // Функция для показа статуса
1285    function showStatus(message, isError = false) {
1286        const statusDiv = document.getElementById('status-message');
1287        if (statusDiv) {
1288            statusDiv.textContent = message;
1289            statusDiv.style.display = 'block';
1290            statusDiv.style.background = isError ? 'rgba(255, 59, 48, 0.9)' : 'rgba(52, 199, 89, 0.9)';
1291            console.log(`Статус: ${message}`);
1292        }
1293    }
1294
1295    // Функция для ожидания
1296    function wait(ms) {
1297        return new Promise(resolve => setTimeout(resolve, ms));
1298    }
1299
1300    // Функция для парсинга числа из строки
1301    function parseNumber(str) {
1302        if (!str) return 0;
1303        // Убираем все символы кроме цифр, точек и запятых
1304        const cleaned = str.replace(/[^\d.,]/g, '').replace(/\s/g, '');
1305        // Заменяем запятую на точку
1306        const normalized = cleaned.replace(',', '.');
1307        return parseFloat(normalized) || 0;
1308    }
1309
1310    // Функция для парсинга процента
1311    function parsePercentage(str) {
1312        if (!str) return 0;
1313        const cleaned = str.replace('%', '').replace(',', '.').trim();
1314        return parseFloat(cleaned) || 0;
1315    }
1316
1317    // Основная функция запуска стратегии
1318    async function runStrategy() {
1319        try {
1320            console.log('Начало выполнения стратегии');
1321            showStatus('Запуск процесса...');
1322
1323            const desiredPercentage = parseFloat(document.getElementById('desired-percentage').value);
1324            if (!desiredPercentage || desiredPercentage <= 0) {
1325                showStatus('Ошибка: введите корректный процент', true);
1326                await handleStrategyError();
1327                return;
1328            }
1329            console.log(`Желаемый процент: ${desiredPercentage}%`);
1330
1331            // Шаг 1: Кликаем на статистику
1332            showStatus('Открытие статистики...');
1333            const statsButton = document.querySelector('.css-amj7dw');
1334            if (!statsButton) {
1335                showStatus('Ошибка: кнопка статистики не найдена', true);
1336                await handleStrategyError();
1337                return;
1338            }
1339            statsButton.click();
1340            console.log('Клик на статистику выполнен');
1341            await wait(2000); // Увеличена задержка для загрузки статистики
1342
1343            // Шаг 1.5: Выбираем режим "Товары"
1344            showStatus('Выбор режима "Товары"...');
1345            const modeLabels = Array.from(document.querySelectorAll('label'));
1346            let modeInput = null;
1347            
1348            for (const label of modeLabels) {
1349                if (label.textContent.trim() === 'Режим') {
1350                    const inputId = label.getAttribute('for');
1351                    if (inputId) {
1352                        modeInput = document.getElementById(inputId);
1353                        console.log(`Найдено поле Режим с id: ${inputId}`);
1354                        break;
1355                    }
1356                }
1357            }
1358            
1359            if (modeInput) {
1360                // Устанавливаем значение "Товары" напрямую
1361                modeInput.value = 'Товары';
1362                
1363                // Триггерим события для React
1364                const inputEvent = new Event('input', { bubbles: true });
1365                const changeEvent = new Event('change', { bubbles: true });
1366                modeInput.dispatchEvent(inputEvent);
1367                modeInput.dispatchEvent(changeEvent);
1368                
1369                console.log('Установлено значение: Товары');
1370                await wait(1000); // Увеличена задержка для загрузки опций
1371                
1372                // Проверяем, появились ли опции в выпадающем списке
1373                const options = document.querySelectorAll('[role="option"]');
1374                console.log(`Найдено опций: ${options.length}`);
1375                
1376                if (options.length > 0) {
1377                    // Ищем опцию "Товары" и кликаем на неё
1378                    const tovarOption = Array.from(options).find(opt => opt.textContent.includes('Товары'));
1379                    if (tovarOption) {
1380                        tovarOption.click();
1381                        console.log('Выбран режим "Товары"');
1382                        await wait(1500); // Увеличена задержка для загрузки данных после выбора режима
1383                    }
1384                }
1385            }
1386
1387            // Шаг 2: Извлекаем данные из статистики
1388            showStatus('Извлечение данных...');
1389            
1390            // Ждем дополнительное время для загрузки статистики
1391            await wait(1000);
1392            
1393            const stats = Array.from(document.querySelectorAll('.MuiTypography-caption.css-1et52kr'));
1394            
1395            let sumOrders = 0;
1396            let ordersCount = 0;
1397            let cartToOrderPercent = 0;
1398
1399            stats.forEach(el => {
1400                const text = el.textContent.trim();
1401                const valueElement = el.closest('.MuiBox-root')?.querySelector('.MuiTypography-h3 .MuiTypography-body1');
1402                const value = valueElement ? valueElement.textContent.trim() : '';
1403
1404                console.log(`Найден показатель: ${text} = ${value}`);
1405
1406                if (text === 'Сумма заказов') {
1407                    sumOrders = parseNumber(value);
1408                    console.log(`Сумма заказов: ${sumOrders}`);
1409                } else if (text === 'Заказов') {
1410                    ordersCount = parseNumber(value);
1411                    console.log(`Заказов: ${ordersCount}`);
1412                } else if (text === 'Корзина → Заказ') {
1413                    cartToOrderPercent = parsePercentage(value);
1414                    console.log(`Корзина → Заказ: ${cartToOrderPercent}%`);
1415                }
1416            });
1417
1418            if (sumOrders === 0 || ordersCount === 0 || cartToOrderPercent === 0) {
1419                showStatus('Ошибка: не удалось получить данные статистики', true);
1420                console.error('Недостаточно данных:', { sumOrders, ordersCount, cartToOrderPercent });
1421                await handleStrategyError();
1422                return;
1423            }
1424
1425            // Шаг 3: Вычисляем стоимость корзины
1426            const cartCost = (sumOrders / ordersCount) * (desiredPercentage / 100) * (cartToOrderPercent / 100);
1427            const cartCostRounded = Math.round(cartCost * 100) / 100;
1428            console.log(`Расчет: (${sumOrders} / ${ordersCount}) * (${desiredPercentage} / 100) * (${cartToOrderPercent} / 100) = ${cartCostRounded}`);
1429            showStatus(`Рассчитано: ${cartCostRounded}`);
1430
1431            // Закрываем статистику
1432            statsButton.click();
1433            await wait(500);
1434
1435            // Шаг 4: Кликаем на "Вставить стратегию"
1436            showStatus('Вставка стратегии...');
1437            const insertButtons = document.querySelectorAll('.css-5kbhos');
1438            let insertButton = null;
1439            
1440            // Ищем кнопку с текстом "Вставить стратегию"
1441            for (const btn of insertButtons) {
1442                if (btn.textContent.includes('Вставить стратегию')) {
1443                    insertButton = btn;
1444                    break;
1445                }
1446            }
1447
1448            if (!insertButton && insertButtons.length >= 2) {
1449                insertButton = insertButtons[1];
1450            } else if (!insertButton && insertButtons.length === 1) {
1451                insertButton = insertButtons[0];
1452            }
1453
1454            if (!insertButton) {
1455                showStatus('Ошибка: кнопка "Вставить стратегию" не найдена', true);
1456                await handleStrategyError();
1457                return;
1458            }
1459
1460            // Получаем текущую выбранную стратегию
1461            const currentStrategyCode = await getCurrentStrategy();
1462            console.log('Используем стратегию, длина:', currentStrategyCode.length);
1463            console.log('Первые 50 символов стратегии:', currentStrategyCode.substring(0, 50));
1464            console.log('Последние 50 символов стратегии:', currentStrategyCode.substring(currentStrategyCode.length - 50));
1465
1466            // Копируем код стратегии в буфер обмена ПЕРЕД открытием модального окна
1467            console.log('Копируем стратегию в буфер обмена...');
1468            
1469            // Пробуем несколько способов копирования
1470            try {
1471                // Способ 1: navigator.clipboard (современный)
1472                await navigator.clipboard.writeText(currentStrategyCode);
1473                console.log('✓ Стратегия скопирована через navigator.clipboard');
1474            } catch (clipboardError) {
1475                console.log('navigator.clipboard не сработал, пробуем GM.setClipboard...');
1476                // Способ 2: GM.setClipboard (fallback)
1477                await GM.setClipboard(currentStrategyCode);
1478                console.log('✓ Стратегия скопирована через GM.setClipboard');
1479            }
1480            
1481            console.log('Длина стратегии:', currentStrategyCode.length);
1482            await wait(500);
1483
1484            insertButton.click();
1485            console.log('Клик на "Вставить стратегию" выполнен');
1486            await wait(1500); // Увеличена задержка для применения стратегии из буфера
1487            
1488            console.log('✓ Стратегия вставлена из буфера обмена');
1489            
1490            await wait(1000);
1491
1492            // Шаг 5: Находим поле "Желаемое значение" и вставляем результат
1493            showStatus('Заполнение поля...');
1494            
1495            // Ищем поле с текстом "За корзину" или "Желаемое значение"
1496            const inputLabels = Array.from(document.querySelectorAll('.MuiInputLabel-root'));
1497            let targetInput = null;
1498
1499            for (const label of inputLabels) {
1500                const labelText = label.textContent;
1501                if (labelText.includes('За корзину') || labelText.includes('Желаемое значение')) {
1502                    const inputId = label.getAttribute('for');
1503                    if (inputId) {
1504                        targetInput = document.getElementById(inputId);
1505                        console.log(`Найдено поле: ${labelText}, id: ${inputId}`);
1506                        break;
1507                    }
1508                }
1509            }
1510
1511            // Если не нашли по лейблу, ищем по имени
1512            if (!targetInput) {
1513                const inputs = document.querySelectorAll('input[type="number"]');
1514                for (const input of inputs) {
1515                    const name = input.getAttribute('name') || '';
1516                    if (name.includes('rules') && name.includes('value')) {
1517                        targetInput = input;
1518                        console.log(`Найдено поле по имени: ${name}`);
1519                        break;
1520                    }
1521                }
1522            }
1523
1524            if (!targetInput) {
1525                showStatus('Ошибка: поле для ввода не найдено', true);
1526                console.error('Не удалось найти поле для ввода значения');
1527                await handleStrategyError();
1528                return;
1529            }
1530
1531            // Устанавливаем значение
1532            targetInput.focus();
1533            targetInput.value = cartCostRounded.toString();
1534            
1535            // Триггерим события для React
1536            const inputEvent = new Event('input', { bubbles: true });
1537            const changeEvent = new Event('change', { bubbles: true });
1538            targetInput.dispatchEvent(inputEvent);
1539            targetInput.dispatchEvent(changeEvent);
1540            
1541            console.log(`Значение ${cartCostRounded} установлено в поле ${targetInput.id}`);
1542            await wait(500);
1543
1544            // Шаг 7: Нажимаем "Сохранить"
1545            showStatus('Сохранение...');
1546            const saveButtons = document.querySelectorAll('button');
1547            let saveButton = null;
1548
1549            for (const btn of saveButtons) {
1550                if (btn.textContent.trim() === 'Сохранить') {
1551                    saveButton = btn;
1552                    break;
1553                }
1554            }
1555
1556            if (!saveButton) {
1557                showStatus('Ошибка: кнопка "Сохранить" не найдена', true);
1558                await handleStrategyError();
1559                return;
1560            }
1561
1562            saveButton.click();
1563            console.log('Клик на "Сохранить" выполнен');
1564            await wait(1000);
1565
1566            showStatus(`✅ Готово! Стоимость корзины: ${cartCostRounded}`);
1567            console.log('Стратегия успешно установлена');
1568
1569            // Шаг 8: Работа с кластерами (только если чекбокс включен)
1570            const applyToClusters = document.getElementById('apply-to-clusters');
1571            const shouldApplyToClusters = applyToClusters ? applyToClusters.checked : true;
1572            
1573            if (!shouldApplyToClusters) {
1574                console.log('Применение стратегии к кластерам отключено');
1575                showStatus('✅ Готово! Кластеры пропущены');
1576            } else {
1577                console.log('Применение стратегии к кластерам включено');
1578                
1579                // 8.1: Переходим во вкладку "Кластеры"
1580                const tabs = Array.from(document.querySelectorAll('button[role="tab"]'));
1581                const clustersTab = tabs.find(tab => tab.textContent.trim() === 'Кластеры');
1582                if (!clustersTab) {
1583                    console.error('Вкладка "Кластеры" не найдена');
1584                    showStatus('⚠️ Вкладка "Кластеры" не найдена, пропускаем', true);
1585                } else {
1586                    clustersTab.click();
1587                    console.log('Клик на вкладку "Кластеры" выполнен');
1588                    await wait(3000); // Увеличена задержка для загрузки кластеров
1589                    
1590                    // Ждем, пока исчезнет скелетон загрузки
1591                    let loadingAttempts = 0;
1592                    while (loadingAttempts < 10) {
1593                        const skeleton = document.querySelector('.MuiSkeleton-root');
1594                        if (!skeleton) {
1595                            console.log('Кластеры загружены');
1596                            break;
1597                        }
1598                        console.log(`Ожидание загрузки кластеров, попытка ${loadingAttempts + 1}`);
1599                        await wait(1000);
1600                        loadingAttempts++;
1601                    }
1602                    
1603                    // 8.2: Выделяем все кластеры - клик в checkbox
1604                    showStatus('Выделение всех кластеров...');
1605                    let selectAllCheckbox = null;
1606                    
1607                    // Способ 1: Ищем через контейнер css-1ytbthu
1608                    const checkboxContainer = document.querySelector('.css-1ytbthu');
1609                    if (checkboxContainer) {
1610                        selectAllCheckbox = checkboxContainer.querySelector('.css-vlug8u');
1611                        console.log('Найден checkbox через контейнер css-1ytbthu');
1612                    }
1613                    
1614                    // Способ 2: Ищем напрямую по классу vlug8u в заголовке таблицы
1615                    if (!selectAllCheckbox) {
1616                        const tableHeader = document.querySelector('thead');
1617                        if (tableHeader) {
1618                            selectAllCheckbox = tableHeader.querySelector('.css-vlug8u');
1619                            console.log('Найден checkbox в заголовке таблицы');
1620                        }
1621                    }
1622                    
1623                    // Способ 3: Ищем первый checkbox в таблице
1624                    if (!selectAllCheckbox) {
1625                        const checkboxes = document.querySelectorAll('input[type="checkbox"]');
1626                        if (checkboxes.length > 0) {
1627                            selectAllCheckbox = checkboxes[0];
1628                            console.log('Найден checkbox через input[type="checkbox"]');
1629                        }
1630                    }
1631                    
1632                    if (!selectAllCheckbox) {
1633                        console.error('Checkbox для выделения всех кластеров не найден');
1634                        showStatus('⚠️ Checkbox не найден, пропускаем кластеры', true);
1635                    } else {
1636                        selectAllCheckbox.click();
1637                        console.log('Все кластеры выделены');
1638                        await wait(1000);
1639                        
1640                        // 8.3: Кликаем на "Действия"
1641                        showStatus('Открытие меню действий...');
1642                        const actionsButton = document.querySelector('.css-1rll63h');
1643                        if (!actionsButton) {
1644                            console.error('Кнопка "Действия" не найдена');
1645                            showStatus('⚠️ Кнопка "Действия" не найдена', true);
1646                        } else {
1647                            actionsButton.click();
1648                            console.log('Клик на "Действия" выполнен');
1649                            await wait(1000);
1650                            
1651                            // 8.4: Кликаем на "Управление" - второй элемент с классом hq58ok
1652                            showStatus('Открытие управления...');
1653                            const managementButtons = document.querySelectorAll('.css-hq58ok');
1654                            if (managementButtons.length < 2) {
1655                                console.error('Кнопка "Управление" не найдена');
1656                                showStatus('⚠️ Кнопка "Управление" не найдена', true);
1657                            } else {
1658                                managementButtons[1].click();
1659                                console.log('Клик на "Управление" выполнен');
1660                                await wait(1500);
1661                                
1662                                // 8.5: Кликаем на "Стратегия" - 3-й элемент с классом css-582wun
1663                                showStatus('Открытие стратегии кластеров...');
1664                                const strategyTabs = document.querySelectorAll('.css-582wun');
1665                                if (strategyTabs.length < 3) {
1666                                    console.error('Вкладка "Стратегия" не найдена');
1667                                    showStatus('⚠️ Вкладка "Стратегия" не найдена', true);
1668                                } else {
1669                                    strategyTabs[2].click();
1670                                    console.log('Клик на "Стратегия" выполнен');
1671                                    await wait(1500);
1672                                    
1673                                    // 8.6: Вставляем стратегию и рассчитанную ставку
1674                                    showStatus('Вставка стратегии для кластеров...');
1675                                    const clusterInsertButtons = document.querySelectorAll('.css-5kbhos');
1676                                    let clusterInsertButton = null;
1677                                    
1678                                    for (const btn of clusterInsertButtons) {
1679                                        if (btn.textContent.includes('Вставить стратегию')) {
1680                                            clusterInsertButton = btn;
1681                                            break;
1682                                        }
1683                                    }
1684                                    
1685                                    if (!clusterInsertButton && clusterInsertButtons.length > 0) {
1686                                        clusterInsertButton = clusterInsertButtons[0];
1687                                    }
1688                                    
1689                                    if (!clusterInsertButton) {
1690                                        console.error('Кнопка "Вставить стратегию" для кластеров не найдена');
1691                                        showStatus('⚠️ Кнопка вставки стратегии не найдена', true);
1692                                    } else {
1693                                        // Получаем текущую кластерную стратегию и копируем в буфер
1694                                        const currentClusterStrategyCode = await getCurrentClusterStrategy();
1695                                        console.log('Используем кластерную стратегию, длина:', currentClusterStrategyCode.length);
1696                                        console.log('Первые 50 символов кластерной стратегии:', currentClusterStrategyCode.substring(0, 50));
1697                                        console.log('Последние 50 символов кластерной стратегии:', currentClusterStrategyCode.substring(currentClusterStrategyCode.length - 50));
1698                                        
1699                                        // Копируем код стратегии в буфер обмена
1700                                        console.log('Копируем кластерную стратегию в буфер обмена...');
1701                                        
1702                                        // Пробуем несколько способов копирования
1703                                        try {
1704                                            // Способ 1: navigator.clipboard (современный)
1705                                            await navigator.clipboard.writeText(currentClusterStrategyCode);
1706                                            console.log('✓ Кластерная стратегия скопирована через navigator.clipboard');
1707                                        } catch (clipboardError) {
1708                                            console.log('navigator.clipboard не сработал, пробуем GM.setClipboard...');
1709                                            // Способ 2: GM.setClipboard (fallback)
1710                                            await GM.setClipboard(currentClusterStrategyCode);
1711                                            console.log('✓ Кластерная стратегия скопирована через GM.setClipboard');
1712                                        }
1713                                        
1714                                        console.log('Длина кластерной стратегии:', currentClusterStrategyCode.length);
1715                                        await wait(500);
1716                                        
1717                                        clusterInsertButton.click();
1718                                        console.log('Клик на "Вставить стратегию" для кластеров выполнен');
1719                                        await wait(1500);
1720                                        
1721                                        // Находим поле для ввода ставки за корзину
1722                                        const clusterInputLabels = Array.from(document.querySelectorAll('.MuiInputLabel-root'));
1723                                        let clusterTargetInput = null;
1724                                        
1725                                        for (const label of clusterInputLabels) {
1726                                            const labelText = label.textContent;
1727                                            if (labelText.includes('За корзину') || labelText.includes('Желаемое значение')) {
1728                                                const inputId = label.getAttribute('for');
1729                                                if (inputId) {
1730                                                    clusterTargetInput = document.getElementById(inputId);
1731                                                    console.log(`Найдено поле для кластеров: ${labelText}`);
1732                                                    break;
1733                                                }
1734                                            }
1735                                        }
1736                                        
1737                                        if (!clusterTargetInput) {
1738                                            const clusterInputs = document.querySelectorAll('input[type="number"]');
1739                                            for (const input of clusterInputs) {
1740                                                const name = input.getAttribute('name') || '';
1741                                                if (name.includes('CostPerAddedToCart') || name.includes('value')) {
1742                                                    clusterTargetInput = input;
1743                                                    console.log(`Найдено поле по имени: ${name}`);
1744                                                    break;
1745                                                }
1746                                            }
1747                                        }
1748                                        
1749                                        if (clusterTargetInput) {
1750                                            clusterTargetInput.focus();
1751                                            clusterTargetInput.value = cartCostRounded.toString();
1752                                            
1753                                            const inputEvent = new Event('input', { bubbles: true });
1754                                            const changeEvent = new Event('change', { bubbles: true });
1755                                            clusterTargetInput.dispatchEvent(inputEvent);
1756                                            clusterTargetInput.dispatchEvent(changeEvent);
1757                                            
1758                                            console.log(`Значение ${cartCostRounded} установлено для кластеров`);
1759                                            await wait(1000);
1760                                        }
1761                                        
1762                                        // Нажимаем "Применить" после вставки стратегии - 2-й элемент с классом css-eqlbov
1763                                        showStatus('Применение стратегии кластеров...');
1764                                        const clusterStrategyApplyButtons = document.querySelectorAll('.css-eqlbov');
1765                                        if (clusterStrategyApplyButtons.length < 2) {
1766                                            console.error('Кнопка "Применить" стратегию для кластеров не найдена');
1767                                            showStatus('⚠️ Кнопка "Применить" стратегию не найдена', true);
1768                                        } else {
1769                                            clusterStrategyApplyButtons[1].click();
1770                                            console.log('Клик на "Применить" стратегию для кластеров выполнен');
1771                                            await wait(1500);
1772                                        }
1773                                        
1774                                        // 8.7: Кликаем на "Автофильтры" - 3-й элемент с классом css-wi74td
1775                                        showStatus('Открытие автофильтров...');
1776                                        const autofilterButtons = document.querySelectorAll('.css-wi74td');
1777                                        if (autofilterButtons.length < 3) {
1778                                            console.error('Кнопка "Автофильтры" не найдена');
1779                                            showStatus('⚠️ Кнопка "Автофильтры" не найдена', true);
1780                                        } else {
1781                                            autofilterButtons[2].click();
1782                                            console.log('Клик на "Автофильтры" выполнен');
1783                                            await wait(1500);
1784                                            
1785                                            // 8.8: Кликаем на "Шаблоны" - 2-й элемент с классом css-l149ws
1786                                            showStatus('Открытие шаблонов...');
1787                                            const templateButtons = document.querySelectorAll('.css-l149ws');
1788                                            if (templateButtons.length < 2) {
1789                                                console.error('Кнопка "Шаблоны" не найдена');
1790                                                showStatus('⚠️ Кнопка "Шаблоны" не найдена', true);
1791                                            } else {
1792                                                templateButtons[1].click();
1793                                                console.log('Клик на "Шаблоны" выполнен');
1794                                                await wait(1500);
1795                                                
1796                                                // 8.9: Выбираем "Расширение" - div с data-id="Расширение" и классом css-1n9drpd
1797                                                showStatus('Выбор шаблона "Расширение"...');
1798                                                
1799                                                // Способ 1: Ищем по data-id="Расширение"
1800                                                let extensionTemplate = document.querySelector('div[data-id="Расширение"]');
1801                                                if (extensionTemplate) {
1802                                                    console.log('Найден шаблон по data-id="Расширение"');
1803                                                }
1804                                                
1805                                                // Способ 2: Ищем по классу css-1n9drpd
1806                                                if (!extensionTemplate) {
1807                                                    extensionTemplate = document.querySelector('.css-1n9drpd');
1808                                                    if (extensionTemplate) {
1809                                                        console.log('Найден шаблон по классу css-1n9drpd');
1810                                                    }
1811                                                }
1812                                                
1813                                                // Способ 3: Ищем по тексту "Расширение"
1814                                                if (!extensionTemplate) {
1815                                                    const allElements = document.querySelectorAll('div, button, span, p');
1816                                                    for (const el of allElements) {
1817                                                        const text = el.textContent.trim();
1818                                                        if (text === 'Расширение' || text.includes('Расширение')) {
1819                                                            extensionTemplate = el;
1820                                                            console.log(`Найден шаблон "Расширение" по тексту, элемент: ${el.tagName}, класс: ${el.className}`);
1821                                                            break;
1822                                                        }
1823                                                    }
1824                                                }
1825                                                
1826                                                if (!extensionTemplate) {
1827                                                    console.error('Шаблон "Расширение" не найден');
1828                                                    console.log('Доступные элементы после клика на Шаблоны:');
1829                                                    const allVisible = document.querySelectorAll('div[data-id], div[class*="css-"]');
1830                                                    allVisible.forEach((el, i) => {
1831                                                        if (i < 20) { // Логируем первые 20 элементов
1832                                                            console.log(`Элемент ${i}: data-id="${el.getAttribute('data-id')}", класс: ${el.className}, текст: ${el.textContent.substring(0, 30)}`);
1833                                                        }
1834                                                    });
1835                                                    showStatus('⚠️ Шаблон "Расширение" не найден', true);
1836                                                } else {
1837                                                    extensionTemplate.click();
1838                                                    console.log(`Шаблон "Расширение" выбран, класс: ${extensionTemplate.className}`);
1839                                                    await wait(1000);
1840                                                }
1841                                            }
1842                                        }
1843                                        
1844                                        // 8.10: Жмем "Сохранить" - класс tn31lt
1845                                        showStatus('Сохранение настроек кластеров...');
1846                                        const clusterSaveButton = document.querySelector('.css-tn31lt');
1847                                        if (!clusterSaveButton) {
1848                                            console.error('Кнопка "Сохранить" для кластеров не найдена');
1849                                            showStatus('⚠️ Кнопка "Сохранить" не найдена', true);
1850                                        } else {
1851                                            clusterSaveButton.click();
1852                                            console.log('Клик на "Сохранить" для кластеров выполнен');
1853                                            await wait(2000);
1854                                            showStatus('✅ Кластеры настроены!');
1855                                        }
1856                                    }
1857                                }
1858                            }
1859                        }
1860                    }
1861                }
1862            }
1863
1864            showStatus(`✅ Полностью готово! Стоимость корзины: ${cartCostRounded}`);
1865            console.log('Стратегия и кластеры успешно настроены');
1866
1867            // Проверяем, есть ли массовая обработка
1868            const savedDRR = await GM.getValue('bulkProcessingDRR', null);
1869            if (savedDRR !== null) {
1870                console.log('Обнаружена массовая обработка, переходим к следующей кампании');
1871                
1872                // Проверяем, не на паузе ли обработка
1873                const isPaused = await GM.getValue('bulkPaused', false);
1874                if (isPaused) {
1875                    console.log('Обработка на паузе, ждем возобновления');
1876                    showStatus('⏸️ Обработка на паузе');
1877                    return;
1878                }
1879                
1880                // Получаем список кампаний и текущий индекс
1881                const campaignsJson = await GM.getValue('bulkCampaigns', null);
1882                const currentIndex = await GM.getValue('bulkCurrentIndex', 0);
1883                
1884                if (campaignsJson) {
1885                    const campaigns = JSON.parse(campaignsJson);
1886                    const nextIndex = currentIndex + 1;
1887                    
1888                    console.log(`Обработано ${nextIndex} из ${campaigns.length} кампаний`);
1889                    
1890                    if (nextIndex < campaigns.length) {
1891                        // Сохраняем новый индекс
1892                        await GM.setValue('bulkCurrentIndex', nextIndex);
1893                        
1894                        // Открываем следующую кампанию в новой вкладке
1895                        console.log(`Открытие кампании ${nextIndex + 1}: ${campaigns[nextIndex]}`);
1896                        await GM.openInTab(campaigns[nextIndex], false);
1897                        
1898                        // Закрываем текущую вкладку
1899                        await wait(1000);
1900                        window.close();
1901                    } else {
1902                        // Все кампании обработаны
1903                        console.log('Все кампании обработаны, очищаем данные');
1904                        await GM.deleteValue('bulkProcessingDRR');
1905                        await GM.deleteValue('bulkCampaigns');
1906                        await GM.deleteValue('bulkCurrentIndex');
1907                        
1908                        // Закрываем текущую вкладку
1909                        showStatus('✅ Все кампании обработаны! Закрытие вкладки...');
1910                        await wait(2000);
1911                        window.close();
1912                    }
1913                }
1914            }
1915
1916        } catch (error) {
1917            console.error('Ошибка при выполнении стратегии:', error);
1918            showStatus(`Ошибка: ${error.message}`, true);
1919            await handleStrategyError();
1920        }
1921    }
1922
1923    // Функция для обработки ошибок и перехода к следующей кампании
1924    async function handleStrategyError() {
1925        const savedDRR = await GM.getValue('bulkProcessingDRR', null);
1926        if (savedDRR !== null) {
1927            console.log('Обнаружена ошибка при массовой обработке, ждем 10 секунд перед переходом к следующей кампании');
1928            showStatus('⚠️ Ошибка! Переход к следующей кампании через 10 секунд...', true);
1929            
1930            // Ждем 10 секунд
1931            for (let i = 10; i > 0; i--) {
1932                showStatus(`⚠️ Ошибка! Переход к следующей через ${i} сек...`, true);
1933                await wait(1000);
1934            }
1935            
1936            // Получаем список кампаний и текущий индекс
1937            const campaignsJson = await GM.getValue('bulkCampaigns', null);
1938            const currentIndex = await GM.getValue('bulkCurrentIndex', 0);
1939            
1940            if (campaignsJson) {
1941                const campaigns = JSON.parse(campaignsJson);
1942                const nextIndex = currentIndex + 1;
1943                
1944                console.log(`Пропускаем кампанию с ошибкой. Переход к ${nextIndex + 1} из ${campaigns.length}`);
1945                
1946                if (nextIndex < campaigns.length) {
1947                    // Сохраняем новый индекс
1948                    await GM.setValue('bulkCurrentIndex', nextIndex);
1949                    
1950                    // Открываем следующую кампанию в новой вкладке
1951                    console.log(`Открытие кампании ${nextIndex + 1}: ${campaigns[nextIndex]}`);
1952                    await GM.openInTab(campaigns[nextIndex], false);
1953                    
1954                    // Закрываем текущую вкладку
1955                    await wait(1000);
1956                    window.close();
1957                } else {
1958                    // Все кампании обработаны
1959                    console.log('Все кампании обработаны, очищаем данные');
1960                    await GM.deleteValue('bulkProcessingDRR');
1961                    await GM.deleteValue('bulkCampaigns');
1962                    await GM.deleteValue('bulkCurrentIndex');
1963                    
1964                    // Закрываем текущую вкладку
1965                    showStatus('✅ Все кампании обработаны! Закрытие вкладки...');
1966                    await wait(2000);
1967                    window.close();
1968                }
1969            }
1970        }
1971    }
1972
1973    // Инициализация
1974    function init() {
1975        console.log('Инициализация расширения');
1976        
1977        // Проверяем, на какой странице мы находимся
1978        if (window.location.href.includes('/advert/campaigns')) {
1979            // Страница со списком кампаний
1980            console.log('Страница списка кампаний обнаружена');
1981            
1982            setTimeout(() => {
1983                if (document.body) {
1984                    createBulkUI();
1985                } else {
1986                    console.error('Body не найден');
1987                }
1988            }, 1000);
1989        } else if (window.location.href.includes('/campaigns/auto-campaigns/') && window.location.href.includes('/campaign')) {
1990            // Страница отдельной кампании
1991            console.log('Страница кампании обнаружена');
1992            
1993            // Создаем UI с небольшой задержкой, чтобы убедиться, что страница загружена
1994            setTimeout(() => {
1995                if (document.body) {
1996                    createUI();
1997                } else {
1998                    console.error('Body не найден');
1999                }
2000            }, 1000);
2001        } else {
2002            console.log('Не на странице кампании, UI не создается');
2003        }
2004    }
2005
2006    // Запускаем инициализацию
2007    init();
2008
2009})();
MP Manager Auto Strategy Setter | Robomonkey