MP Manager Cluster Auto Strategy Setter

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

Size

139.8 KB

Version

1.8.116

Created

Feb 17, 2026

Updated

20 days ago

1// ==UserScript==
2// @name		MP Manager Cluster Auto Strategy Setter
3// @description		Автоматическая установка стратегии рекламной кампании на основе статистики
4// @version		1.8.116
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 = 'eyJjYW1wYWlnblR5cGUiOiJTZWFyY2hDYXRhbG9nIiwidmVyc2lvbiI6MiwiZGF0YSI6eyJzdGF0ZSI6IkVuYWJsZWQiLCJtb2RlIjp7InR5cGUiOiJQb3NpdGlvbiIsInBhdXNlVHlwZSI6IlJlc3VtZSJ9LCJzdHJhdGVneSI6eyJ0eXBlIjoiQ2FtcGFpZ25TdGF0cyIsIm1vZGUiOiJQbGFjZSIsImJpZE1vZGUiOiJDb3N0UGVyQ2xpY2siLCJjYW1wYWlnblN0YXRzIjp7Im1heFByaWNlIjo2MCwibWluUHJpY2UiOjEsInBsYXRmb3JtcyI6W10sImludGVydmFsIjoiV2VlayIsInJ1bGVzIjpbeyJ0eXBlIjoiQ29zdFBlckFkZGVkVG9DYXJ0IiwibW9kZSI6IlZhbHVlIiwidmFsdWUiOiIifV19fSwicGxhY2VTdHJhdGVneSI6eyJ0eXBlIjoiS2V5d29yZHMiLCJrZXl3b3JkcyI6eyJrZXl3b3JkcyI6W119fSwiaXNDbHVzdGVyIjp0cnVlfX0=';
21    
22    // Стратегия для удержания места (обычная)
23    const HOLD_POSITION_STRATEGY_CODE = 'eyJjYW1wYWlnblR5cGUiOiJTZWFyY2hDYXRhbG9nIiwidmVyc2lvbiI6MiwiZGF0YSI6eyJzdGF0ZSI6IkVuYWJsZWQiLCJtb2RlIjp7InR5cGUiOiJQb3NpdGlvbiIsInBhdXNlVHlwZSI6IlJlc3VtZSJ9LCJzdHJhdGVneSI6eyJ0eXBlIjoiQ2FtcGFpZ25TdGF0cyIsIm1vZGUiOiJQbGFjZSIsImJpZE1vZGUiOiJDb3N0UGVyQ2xpY2siLCJjYW1wYWlnblN0YXRzIjp7Im1heFByaWNlIjo2MCwibWluUHJpY2UiOjEsInBsYXRmb3JtcyI6W10sImludGVydmFsIjoiV2VlayIsInJ1bGVzIjpbeyJ0eXBlIjoiQ29zdFBlckFkZGVkVG9DYXJ0IiwibW9kZSI6IlZhbHVlIiwidmFsdWUiOiIifV19fSwicGxhY2VTdHJhdGVneSI6eyJ0eXBlIjoiS2V5d29yZHMiLCJrZXl3b3JkcyI6eyJrZXl3b3JkcyI6W119fSwiaXNDbHVzdGVyIjpmYWxzZX19';
24
25    // Стратегия для удержания места (кластерная)
26    const HOLD_POSITION_CLUSTER_STRATEGY_CODE = 'eyJjYW1wYWlnblR5cGUiOiJTZWFyY2hDYXRhbG9nIiwidmVyc2lvbiI6MiwiZGF0YSI6eyJzdGF0ZSI6IkVuYWJsZWQiLCJtb2RlIjp7InR5cGUiOiJQb3NpdGlvbiIsInBhdXNlVHlwZSI6IlJlc3VtZSJ9LCJzdHJhdGVneSI6eyJ0eXBlIjoiQ2FtcGFpZ25TdGF0cyIsIm1vZGUiOiJQbGFjZSIsImJpZE1vZGUiOiJDb3N0UGVyQ2xpY2siLCJjbHVzdGVyU3RhdHMiOnsibWF4QmlkIjo4MDAwLCJtaW5CaWQiOjQwMCwiaW50ZXJ2YWwiOiJUaHJlZURheXMiLCJydWxlcyI6W3sidHlwZSI6IkF2ZXJhZ2VQb3NpdGlvbiIsIm1vZGUiOiJWYWx1ZSIsInZhbHVlIjoyfSx7InR5cGUiOiJDb3N0UGVyQWRkZWRUb0NhcnQiLCJtb2RlIjoiQXZlcmFnZVZhbHVlIn1dfSwicGxhY2VTdHJhdGVneSI6eyJ0eXBlIjoiS2V5d29yZHMiLCJrZXl3b3JkcyI6eyJrZXl3b3JkcyI6W119fSwiaXNDbHVzdGVyIjp0cnVlfX0=';
27    
28    // Глобальные переменные для массовой обработки
29    let isBulkProcessing = false;
30    let bulkDesiredPercentage = 30;
31    let bulkPaused = false;
32
33    // Функция для получения сохраненных стратегий
34    async function getSavedStrategies() {
35        let strategies = await GM.getValue('saved_strategies', []);
36        
37        // Миграция: добавляем ID к стратегиям, у которых его нет
38        let needsMigration = false;
39        strategies = strategies.map((strategy, index) => {
40            if (!strategy.id) {
41                needsMigration = true;
42                return {
43                    ...strategy,
44                    id: 'strategy_migrated_' + Date.now() + '_' + index
45                };
46            }
47            return strategy;
48        });
49        
50        // Сохраняем обновленные стратегии, если была миграция
51        if (needsMigration) {
52            await GM.setValue('saved_strategies', strategies);
53            console.log('Миграция стратегий выполнена: добавлены ID');
54        }
55        
56        // Если нет сохраненных стратегий, добавляем стратегию по умолчанию
57        if (strategies.length === 0) {
58            return [{
59                id: 'default',
60                name: 'Стратегия по умолчанию',
61                data: STRATEGY_CODE
62            }];
63        }
64        return strategies;
65    }
66
67    // Функция для получения сохраненных стратегий для кластеров
68    async function getSavedClusterStrategies() {
69        let strategies = await GM.getValue('saved_cluster_strategies', []);
70        
71        // Миграция: добавляем ID к стратегиям, у которых его нет
72        let needsMigration = false;
73        strategies = strategies.map((strategy, index) => {
74            if (!strategy.id) {
75                needsMigration = true;
76                return {
77                    ...strategy,
78                    id: 'cluster_strategy_migrated_' + Date.now() + '_' + index
79                };
80            }
81            return strategy;
82        });
83        
84        // Сохраняем обновленные стратегии, если была миграция
85        if (needsMigration) {
86            await GM.setValue('saved_cluster_strategies', strategies);
87            console.log('Миграция кластерных стратегий выполнена: добавлены ID');
88        }
89        
90        // Если нет сохраненных стратегий, добавляем стратегию по умолчанию
91        if (strategies.length === 0) {
92            return [{
93                id: 'cluster_default',
94                name: 'Кластерная стратегия по умолчанию',
95                data: CLUSTER_STRATEGY_CODE
96            }];
97        }
98        return strategies;
99    }
100
101    // Функция для получения текущей стратегии
102    async function getCurrentStrategy() {
103        const currentId = await GM.getValue('current_strategy_id', 'default');
104        const strategies = await getSavedStrategies();
105        const strategy = strategies.find(s => s.id === currentId);
106        return strategy ? strategy.data : STRATEGY_CODE;
107    }
108
109    // Функция для получения текущей кластерной стратегии
110    async function getCurrentClusterStrategy() {
111        const currentId = await GM.getValue('current_cluster_strategy_id', 'cluster_default');
112        const strategies = await getSavedClusterStrategies();
113        const strategy = strategies.find(s => s.id === currentId);
114        return strategy ? strategy.data : CLUSTER_STRATEGY_CODE;
115    }
116
117    // Функция для получения стратегии удержания места
118    async function getHoldPositionStrategy() {
119        const holdPositionId = await GM.getValue('hold_position_strategy_id', null);
120        if (holdPositionId) {
121            const strategies = await getSavedStrategies();
122            const strategy = strategies.find(s => s.id === holdPositionId);
123            if (strategy) {
124                return strategy.data;
125            }
126        }
127        // Если стратегия удержания места не установлена, используем текущую выбранную стратегию
128        const currentId = await GM.getValue('current_strategy_id', 'default');
129        if (currentId !== 'default') {
130            const strategies = await getSavedStrategies();
131            const strategy = strategies.find(s => s.id === currentId);
132            if (strategy) {
133                console.log('⚠️ Стратегия удержания места не установлена, используем текущую стратегию:', strategy.name);
134                return strategy.data;
135            }
136        }
137        // Возвращаем специальную стратегию удержания места по умолчанию
138        return HOLD_POSITION_STRATEGY_CODE;
139    }
140
141    // Функция для получения кластерной стратегии удержания места
142    async function getHoldPositionClusterStrategy() {
143        const holdPositionId = await GM.getValue('hold_position_cluster_strategy_id', null);
144        if (holdPositionId) {
145            const strategies = await getSavedClusterStrategies();
146            const strategy = strategies.find(s => s.id === holdPositionId);
147            if (strategy) {
148                return strategy.data;
149            }
150        }
151        // Возвращаем специальную кластерную стратегию удержания места по умолчанию
152        return HOLD_POSITION_CLUSTER_STRATEGY_CODE;
153    }
154
155    // Функция для создания модального окна управления стратегиями
156    function createStrategyManagementModal() {
157        return new Promise(async (resolve) => {
158            // Создаем оверлей
159            const overlay = document.createElement('div');
160            overlay.style.cssText = `
161                position: fixed;
162                top: 0;
163                left: 0;
164                width: 100%;
165                height: 100%;
166                background: rgba(0, 0, 0, 0.5);
167                display: flex;
168                justify-content: center;
169                align-items: center;
170                z-index: 10001;
171            `;
172            
173            // Создаем модальное окно
174            const modal = document.createElement('div');
175            modal.style.cssText = `
176                background: white;
177                border-radius: 12px;
178                padding: 24px;
179                min-width: 500px;
180                max-width: 600px;
181                max-height: 80vh;
182                overflow-y: auto;
183                box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);
184            `;
185            
186            // Заголовок
187            const title = document.createElement('h2');
188            title.textContent = 'Управление стратегиями';
189            title.style.cssText = `
190                margin: 0 0 20px 0;
191                font-size: 24px;
192                font-weight: bold;
193                color: #333;
194            `;
195            modal.appendChild(title);
196            
197            // Контейнер для списка стратегий
198            const listContainer = document.createElement('div');
199            listContainer.style.cssText = `
200                margin-bottom: 20px;
201                max-height: 300px;
202                overflow-y: auto;
203            `;
204            
205            // Функция для обновления списка
206            const updateList = async () => {
207                const currentStrategies = await getSavedStrategies();
208                const selectedStrategy = await GM.getValue('current_strategy_id', 'default');
209                const holdPositionStrategyId = await GM.getValue('hold_position_strategy_id', null);
210                listContainer.innerHTML = '';
211                
212                if (currentStrategies.length === 0) {
213                    const emptyMessage = document.createElement('p');
214                    emptyMessage.textContent = 'Нет сохраненных стратегий. Используется стратегия по умолчанию.';
215                    emptyMessage.style.cssText = `
216                        color: #666;
217                        font-style: italic;
218                        padding: 20px;
219                        text-align: center;
220                    `;
221                    listContainer.appendChild(emptyMessage);
222                } else {
223                    currentStrategies.forEach((strategy, index) => {
224                        const item = document.createElement('div');
225                        const isSelected = strategy.id === selectedStrategy;
226                        const isHoldPosition = strategy.id === holdPositionStrategyId;
227                        item.style.cssText = `
228                            display: flex;
229                            justify-content: space-between;
230                            align-items: center;
231                            padding: 12px;
232                            margin-bottom: 8px;
233                            background: ${isSelected ? '#e3f2fd' : '#f5f5f5'};
234                            border-radius: 8px;
235                            border: ${isSelected ? '2px solid #2196f3' : '1px solid #ddd'};
236                        `;
237                        
238                        const nameSpan = document.createElement('span');
239                        nameSpan.textContent = strategy.name + (isSelected ? ' ✓' : '') + (isHoldPosition ? ' 📍' : '');
240                        nameSpan.style.cssText = `
241                            font-size: 16px;
242                            color: #333;
243                            flex: 1;
244                            font-weight: ${isSelected ? 'bold' : 'normal'};
245                        `;
246                        
247                        const buttonsContainer = document.createElement('div');
248                        buttonsContainer.style.cssText = `
249                            display: flex;
250                            gap: 8px;
251                        `;
252                        
253                        // Кнопка выбора
254                        if (!isSelected) {
255                            const selectBtn = document.createElement('button');
256                            selectBtn.textContent = '✓ Выбрать';
257                            selectBtn.style.cssText = `
258                                background: #2196f3;
259                                color: white;
260                                border: none;
261                                padding: 6px 12px;
262                                border-radius: 6px;
263                                cursor: pointer;
264                                font-size: 14px;
265                            `;
266                            selectBtn.onmouseover = () => selectBtn.style.background = '#1976d2';
267                            selectBtn.onmouseout = () => selectBtn.style.background = '#2196f3';
268                            selectBtn.onclick = async () => {
269                                await GM.setValue('current_strategy_id', strategy.id);
270                                console.log(`Выбрана стратегия: ${strategy.name} (ID: ${strategy.id})`);
271                                await updateList();
272                            };
273                            buttonsContainer.appendChild(selectBtn);
274                        }
275                        
276                        // Кнопка "Удержание места"
277                        const holdBtn = document.createElement('button');
278                        holdBtn.textContent = isHoldPosition ? '📍 Удалить' : '📍 Удержание';
279                        holdBtn.style.cssText = `
280                            background: ${isHoldPosition ? '#ff9800' : '#4caf50'};
281                            color: white;
282                            border: none;
283                            padding: 6px 12px;
284                            border-radius: 6px;
285                            cursor: pointer;
286                            font-size: 14px;
287                        `;
288                        holdBtn.onmouseover = () => holdBtn.style.background = isHoldPosition ? '#f57c00' : '#45a049';
289                        holdBtn.onmouseout = () => holdBtn.style.background = isHoldPosition ? '#ff9800' : '#4caf50';
290                        holdBtn.onclick = async () => {
291                            if (isHoldPosition) {
292                                await GM.deleteValue('hold_position_strategy_id');
293                                console.log('Стратегия удержания места удалена');
294                            } else {
295                                await GM.setValue('hold_position_strategy_id', strategy.id);
296                                console.log(`Установлена стратегия удержания места: ${strategy.name} (ID: ${strategy.id})`);
297                            }
298                            await updateList();
299                        };
300                        buttonsContainer.appendChild(holdBtn);
301                        
302                        // Кнопка удаления
303                        const deleteBtn = document.createElement('button');
304                        deleteBtn.textContent = '🗑️';
305                        deleteBtn.style.cssText = `
306                            background: #f44336;
307                            color: white;
308                            border: none;
309                            padding: 6px 12px;
310                            border-radius: 6px;
311                            cursor: pointer;
312                            font-size: 14px;
313                        `;
314                        deleteBtn.onmouseover = () => deleteBtn.style.background = '#d32f2f';
315                        deleteBtn.onmouseout = () => deleteBtn.style.background = '#f44336';
316                        deleteBtn.onclick = async () => {
317                            if (confirm(`Удалить стратегию "${strategy.name}"?`)) {
318                                currentStrategies.splice(index, 1);
319                                await GM.setValue('saved_strategies', currentStrategies);
320                                // Если удаляем выбранную стратегию, возвращаемся к дефолтной
321                                if (isSelected) {
322                                    await GM.setValue('current_strategy_id', 'default');
323                                }
324                                // Если удаляем стратегию удержания места, очищаем её
325                                if (isHoldPosition) {
326                                    await GM.deleteValue('hold_position_strategy_id');
327                                }
328                                await updateList();
329                            }
330                        };
331                        buttonsContainer.appendChild(deleteBtn);
332                        
333                        item.appendChild(nameSpan);
334                        item.appendChild(buttonsContainer);
335                        listContainer.appendChild(item);
336                    });
337                }
338            };
339            
340            await updateList();
341            modal.appendChild(listContainer);
342            
343            // Кнопка добавления стратегии
344            const addButton = document.createElement('button');
345            addButton.textContent = '➕ Добавить новую стратегию';
346            addButton.style.cssText = `
347                width: 100%;
348                background: #4caf50;
349                color: white;
350                border: none;
351                padding: 12px;
352                border-radius: 8px;
353                cursor: pointer;
354                font-size: 16px;
355                font-weight: bold;
356                margin-bottom: 12px;
357            `;
358            addButton.onmouseover = () => addButton.style.background = '#45a049';
359            addButton.onmouseout = () => addButton.style.background = '#4caf50';
360            addButton.onclick = async () => {
361                const name = prompt('Введите название стратегии:');
362                if (!name) return;
363                
364                const data = prompt('Вставьте код стратегии (скопируйте из MP Manager):');
365                if (!data) return;
366                
367                const currentStrategies = await GM.getValue('saved_strategies', []);
368                const newId = 'strategy_' + Date.now() + '_' + Math.random().toString(36).substr(2, 9);
369                currentStrategies.push({ id: newId, name, data });
370                await GM.setValue('saved_strategies', currentStrategies);
371                alert(`Стратегия "${name}" сохранена!`);
372                await updateList();
373            };
374            modal.appendChild(addButton);
375            
376            // Кнопка закрытия
377            const closeButton = document.createElement('button');
378            closeButton.textContent = 'Закрыть';
379            closeButton.style.cssText = `
380                width: 100%;
381                background: #666;
382                color: white;
383                border: none;
384                padding: 12px;
385                border-radius: 8px;
386                cursor: pointer;
387                font-size: 16px;
388            `;
389            closeButton.onmouseover = () => closeButton.style.background = '#555';
390            closeButton.onmouseout = () => closeButton.style.background = '#666';
391            closeButton.onclick = () => {
392                document.body.removeChild(overlay);
393                resolve();
394            };
395            modal.appendChild(closeButton);
396            
397            overlay.appendChild(modal);
398            document.body.appendChild(overlay);
399            
400            // Закрытие по клику на оверлей
401            overlay.onclick = (e) => {
402                if (e.target === overlay) {
403                    document.body.removeChild(overlay);
404                    resolve();
405                }
406            };
407        });
408    }
409
410    // Функция для создания модального окна управления кластерными стратегиями
411    function createClusterStrategyManagementModal() {
412        return new Promise(async (resolve) => {
413            // Создаем оверлей
414            const overlay = document.createElement('div');
415            overlay.style.cssText = `
416                position: fixed;
417                top: 0;
418                left: 0;
419                width: 100%;
420                height: 100%;
421                background: rgba(0, 0, 0, 0.5);
422                display: flex;
423                justify-content: center;
424                align-items: center;
425                z-index: 10001;
426            `;
427            
428            // Создаем модальное окно
429            const modal = document.createElement('div');
430            modal.style.cssText = `
431                background: white;
432                border-radius: 12px;
433                padding: 24px;
434                min-width: 500px;
435                max-width: 600px;
436                max-height: 80vh;
437                overflow-y: auto;
438                box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);
439            `;
440            
441            // Заголовок
442            const title = document.createElement('h2');
443            title.textContent = 'Управление стратегиями для кластеров';
444            title.style.cssText = `
445                margin: 0 0 20px 0;
446                font-size: 24px;
447                font-weight: bold;
448                color: #333;
449            `;
450            modal.appendChild(title);
451            
452            // Контейнер для списка стратегий
453            const listContainer = document.createElement('div');
454            listContainer.style.cssText = `
455                margin-bottom: 20px;
456                max-height: 300px;
457                overflow-y: auto;
458            `;
459            
460            // Функция для обновления списка
461            const updateList = async () => {
462                const currentStrategies = await getSavedClusterStrategies();
463                const selectedStrategy = await GM.getValue('current_cluster_strategy_id', 'cluster_default');
464                const holdPositionStrategyId = await GM.getValue('hold_position_cluster_strategy_id', null);
465                listContainer.innerHTML = '';
466                
467                if (currentStrategies.length === 0) {
468                    const emptyMessage = document.createElement('p');
469                    emptyMessage.textContent = 'Нет сохраненных кластерных стратегий. Используется стратегия по умолчанию.';
470                    emptyMessage.style.cssText = `
471                        color: #666;
472                        font-style: italic;
473                        padding: 20px;
474                        text-align: center;
475                    `;
476                    listContainer.appendChild(emptyMessage);
477                } else {
478                    currentStrategies.forEach((strategy, index) => {
479                        const item = document.createElement('div');
480                        const isSelected = strategy.id === selectedStrategy;
481                        const isHoldPosition = strategy.id === holdPositionStrategyId;
482                        item.style.cssText = `
483                            display: flex;
484                            justify-content: space-between;
485                            align-items: center;
486                            padding: 12px;
487                            margin-bottom: 8px;
488                            background: ${isSelected ? '#e3f2fd' : '#f5f5f5'};
489                            border-radius: 8px;
490                            border: ${isSelected ? '2px solid #2196f3' : '1px solid #ddd'};
491                        `;
492                        
493                        const nameSpan = document.createElement('span');
494                        nameSpan.textContent = strategy.name + (isSelected ? ' ✓' : '') + (isHoldPosition ? ' 📍' : '');
495                        nameSpan.style.cssText = `
496                            font-size: 16px;
497                            color: #333;
498                            flex: 1;
499                            font-weight: ${isSelected ? 'bold' : 'normal'};
500                        `;
501                        
502                        const buttonsContainer = document.createElement('div');
503                        buttonsContainer.style.cssText = `
504                            display: flex;
505                            gap: 8px;
506                        `;
507                        
508                        // Кнопка выбора
509                        if (!isSelected) {
510                            const selectBtn = document.createElement('button');
511                            selectBtn.textContent = '✓ Выбрать';
512                            selectBtn.style.cssText = `
513                                background: #2196f3;
514                                color: white;
515                                border: none;
516                                padding: 6px 12px;
517                                border-radius: 6px;
518                                cursor: pointer;
519                                font-size: 14px;
520                            `;
521                            selectBtn.onmouseover = () => selectBtn.style.background = '#1976d2';
522                            selectBtn.onmouseout = () => selectBtn.style.background = '#2196f3';
523                            selectBtn.onclick = async () => {
524                                await GM.setValue('current_cluster_strategy_id', strategy.id);
525                                console.log(`Выбрана кластерная стратегия: ${strategy.name} (ID: ${strategy.id})`);
526                                await updateList();
527                            };
528                            buttonsContainer.appendChild(selectBtn);
529                        }
530                        
531                        // Кнопка "Удержание места"
532                        const holdBtn = document.createElement('button');
533                        holdBtn.textContent = isHoldPosition ? '📍 Удалить' : '📍 Удержание';
534                        holdBtn.style.cssText = `
535                            background: ${isHoldPosition ? '#ff9800' : '#4caf50'};
536                            color: white;
537                            border: none;
538                            padding: 6px 12px;
539                            border-radius: 6px;
540                            cursor: pointer;
541                            font-size: 14px;
542                        `;
543                        holdBtn.onmouseover = () => holdBtn.style.background = isHoldPosition ? '#f57c00' : '#45a049';
544                        holdBtn.onmouseout = () => holdBtn.style.background = isHoldPosition ? '#ff9800' : '#4caf50';
545                        holdBtn.onclick = async () => {
546                            if (isHoldPosition) {
547                                await GM.deleteValue('hold_position_cluster_strategy_id');
548                                console.log('Кластерная стратегия удержания места удалена');
549                            } else {
550                                await GM.setValue('hold_position_cluster_strategy_id', strategy.id);
551                                console.log(`Установлена кластерная стратегия удержания места: ${strategy.name} (ID: ${strategy.id})`);
552                            }
553                            await updateList();
554                        };
555                        buttonsContainer.appendChild(holdBtn);
556                        
557                        // Кнопка удаления
558                        const deleteBtn = document.createElement('button');
559                        deleteBtn.textContent = '🗑️';
560                        deleteBtn.style.cssText = `
561                            background: #f44336;
562                            color: white;
563                            border: none;
564                            padding: 6px 12px;
565                            border-radius: 6px;
566                            cursor: pointer;
567                            font-size: 14px;
568                        `;
569                        deleteBtn.onmouseover = () => deleteBtn.style.background = '#d32f2f';
570                        deleteBtn.onmouseout = () => deleteBtn.style.background = '#f44336';
571                        deleteBtn.onclick = async () => {
572                            if (confirm(`Удалить кластерную стратегию "${strategy.name}"?`)) {
573                                currentStrategies.splice(index, 1);
574                                await GM.setValue('saved_cluster_strategies', currentStrategies);
575                                // Если удаляем выбранную стратегию, возвращаемся к дефолтной
576                                if (isSelected) {
577                                    await GM.setValue('current_cluster_strategy_id', 'cluster_default');
578                                }
579                                // Если удаляем стратегию удержания места, очищаем её
580                                if (isHoldPosition) {
581                                    await GM.deleteValue('hold_position_cluster_strategy_id');
582                                }
583                                await updateList();
584                            }
585                        };
586                        buttonsContainer.appendChild(deleteBtn);
587                        
588                        item.appendChild(nameSpan);
589                        item.appendChild(buttonsContainer);
590                        listContainer.appendChild(item);
591                    });
592                }
593            };
594            
595            await updateList();
596            modal.appendChild(listContainer);
597            
598            // Кнопка добавления стратегии
599            const addButton = document.createElement('button');
600            addButton.textContent = '➕ Добавить новую кластерную стратегию';
601            addButton.style.cssText = `
602                width: 100%;
603                background: #4caf50;
604                color: white;
605                border: none;
606                padding: 12px;
607                border-radius: 8px;
608                cursor: pointer;
609                font-size: 16px;
610                font-weight: bold;
611                margin-bottom: 12px;
612            `;
613            addButton.onmouseover = () => addButton.style.background = '#45a049';
614            addButton.onmouseout = () => addButton.style.background = '#4caf50';
615            addButton.onclick = async () => {
616                const name = prompt('Введите название кластерной стратегии:');
617                if (!name) return;
618                
619                const data = prompt('Вставьте код кластерной стратегии (скопируйте из MP Manager):');
620                if (!data) return;
621                
622                const currentStrategies = await GM.getValue('saved_cluster_strategies', []);
623                const newId = 'cluster_strategy_' + Date.now() + '_' + Math.random().toString(36).substr(2, 9);
624                currentStrategies.push({ id: newId, name, data });
625                await GM.setValue('saved_cluster_strategies', currentStrategies);
626                alert(`Кластерная стратегия "${name}" сохранена!`);
627                await updateList();
628            };
629            modal.appendChild(addButton);
630            
631            // Кнопка закрытия
632            const closeButton = document.createElement('button');
633            closeButton.textContent = 'Закрыть';
634            closeButton.style.cssText = `
635                width: 100%;
636                background: #666;
637                color: white;
638                border: none;
639                padding: 12px;
640                border-radius: 8px;
641                cursor: pointer;
642                font-size: 16px;
643            `;
644            closeButton.onmouseover = () => closeButton.style.background = '#555';
645            closeButton.onmouseout = () => closeButton.style.background = '#666';
646            closeButton.onclick = () => {
647                document.body.removeChild(overlay);
648                resolve();
649            };
650            modal.appendChild(closeButton);
651            
652            overlay.appendChild(modal);
653            document.body.appendChild(overlay);
654            
655            // Закрытие по клику на оверлей
656            overlay.onclick = (e) => {
657                if (e.target === overlay) {
658                    document.body.removeChild(overlay);
659                    resolve();
660                }
661            };
662        });
663    }
664
665    // Функция для создания модального окна управления стратегиями удержания места
666    function createHoldPositionStrategyManagementModal() {
667        return new Promise(async (resolve) => {
668            // Создаем оверлей
669            const overlay = document.createElement('div');
670            overlay.style.cssText = `
671                position: fixed;
672                top: 0;
673                left: 0;
674                width: 100%;
675                height: 100%;
676                background: rgba(0, 0, 0, 0.5);
677                display: flex;
678                justify-content: center;
679                align-items: center;
680                z-index: 10001;
681            `;
682            
683            // Создаем модальное окно
684            const modal = document.createElement('div');
685            modal.style.cssText = `
686                background: white;
687                border-radius: 12px;
688                padding: 24px;
689                min-width: 500px;
690                max-width: 600px;
691                max-height: 80vh;
692                overflow-y: auto;
693                box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);
694            `;
695            
696            // Заголовок
697            const title = document.createElement('h2');
698            title.textContent = 'Стратегии удержания места';
699            title.style.cssText = `
700                margin: 0 0 20px 0;
701                font-size: 24px;
702                font-weight: bold;
703                color: #333;
704            `;
705            modal.appendChild(title);
706            
707            // Описание
708            const description = document.createElement('p');
709            description.textContent = 'Здесь вы можете управлять стратегиями для обычных кампаний и кластеров, которые будут применяться при включенном чекбоксе "Удержание места".';
710            description.style.cssText = `
711                margin: 0 0 20px 0;
712                font-size: 14px;
713                color: #666;
714            `;
715            modal.appendChild(description);
716            
717            // Секция для обычных стратегий
718            const normalSection = document.createElement('div');
719            normalSection.style.cssText = `
720                margin-bottom: 30px;
721                padding: 15px;
722                background: #f9f9f9;
723                border-radius: 8px;
724            `;
725            
726            const normalTitle = document.createElement('h3');
727            normalTitle.textContent = '📋 Обычные кампании';
728            normalTitle.style.cssText = `
729                margin: 0 0 15px 0;
730                font-size: 18px;
731                font-weight: bold;
732                color: #333;
733            `;
734            normalSection.appendChild(normalTitle);
735            
736            const normalListContainer = document.createElement('div');
737            normalListContainer.style.cssText = `
738                margin-bottom: 15px;
739                max-height: 200px;
740                overflow-y: auto;
741            `;
742            
743            // Функция для обновления списка обычных стратегий
744            const updateNormalList = async () => {
745                const strategies = await getSavedStrategies();
746                const holdPositionStrategyId = await GM.getValue('hold_position_strategy_id', null);
747                normalListContainer.innerHTML = '';
748                
749                if (strategies.length === 0) {
750                    const emptyMessage = document.createElement('p');
751                    emptyMessage.textContent = 'Нет сохраненных стратегий.';
752                    emptyMessage.style.cssText = `
753                        color: #666;
754                        font-style: italic;
755                        padding: 10px;
756                        text-align: center;
757                    `;
758                    normalListContainer.appendChild(emptyMessage);
759                } else {
760                    strategies.forEach((strategy) => {
761                        const item = document.createElement('div');
762                        const isHoldPosition = strategy.id === holdPositionStrategyId;
763                        item.style.cssText = `
764                            display: flex;
765                            justify-content: space-between;
766                            align-items: center;
767                            padding: 10px;
768                            margin-bottom: 8px;
769                            background: ${isHoldPosition ? '#e8f5e9' : 'white'};
770                            border-radius: 6px;
771                            border: ${isHoldPosition ? '2px solid #4caf50' : '1px solid #ddd'};
772                        `;
773                        
774                        const nameSpan = document.createElement('span');
775                        nameSpan.textContent = strategy.name + (isHoldPosition ? ' ✓' : '');
776                        nameSpan.style.cssText = `
777                            font-size: 14px;
778                            color: #333;
779                            flex: 1;
780                            font-weight: ${isHoldPosition ? 'bold' : 'normal'};
781                        `;
782                        
783                        const selectBtn = document.createElement('button');
784                        selectBtn.textContent = isHoldPosition ? '✓ Выбрана' : 'Выбрать';
785                        selectBtn.disabled = isHoldPosition;
786                        selectBtn.style.cssText = `
787                            background: ${isHoldPosition ? '#4caf50' : '#2196f3'};
788                            color: white;
789                            border: none;
790                            padding: 6px 12px;
791                            border-radius: 6px;
792                            cursor: ${isHoldPosition ? 'default' : 'pointer'};
793                            font-size: 13px;
794                            opacity: ${isHoldPosition ? '0.7' : '1'};
795                        `;
796                        if (!isHoldPosition) {
797                            selectBtn.onmouseover = () => selectBtn.style.background = '#1976d2';
798                            selectBtn.onmouseout = () => selectBtn.style.background = '#2196f3';
799                            selectBtn.onclick = async () => {
800                                await GM.setValue('hold_position_strategy_id', strategy.id);
801                                console.log(`Установлена стратегия удержания места: ${strategy.name}`);
802                                await updateNormalList();
803                            };
804                        }
805                        
806                        item.appendChild(nameSpan);
807                        item.appendChild(selectBtn);
808                        normalListContainer.appendChild(item);
809                    });
810                }
811            };
812            
813            await updateNormalList();
814            normalSection.appendChild(normalListContainer);
815            
816            const normalResetBtn = document.createElement('button');
817            normalResetBtn.textContent = '🔄 Сбросить на стандартную';
818            normalResetBtn.style.cssText = `
819                width: 100%;
820                background: #ff9800;
821                color: white;
822                border: none;
823                padding: 10px;
824                border-radius: 6px;
825                cursor: pointer;
826                font-size: 14px;
827                font-weight: 600;
828            `;
829            normalResetBtn.onmouseover = () => normalResetBtn.style.background = '#f57c00';
830            normalResetBtn.onmouseout = () => normalResetBtn.style.background = '#ff9800';
831            normalResetBtn.onclick = async () => {
832                await GM.deleteValue('hold_position_strategy_id');
833                console.log('Стратегия удержания места сброшена на стандартную');
834                await updateNormalList();
835            };
836            normalSection.appendChild(normalResetBtn);
837            
838            modal.appendChild(normalSection);
839            
840            // Секция для кластерных стратегий
841            const clusterSection = document.createElement('div');
842            clusterSection.style.cssText = `
843                margin-bottom: 20px;
844                padding: 15px;
845                background: #f9f9f9;
846                border-radius: 8px;
847            `;
848            
849            const clusterTitle = document.createElement('h3');
850            clusterTitle.textContent = '🎯 Кластеры';
851            clusterTitle.style.cssText = `
852                margin: 0 0 15px 0;
853                font-size: 18px;
854                font-weight: bold;
855                color: #333;
856            `;
857            clusterSection.appendChild(clusterTitle);
858            
859            const clusterListContainer = document.createElement('div');
860            clusterListContainer.style.cssText = `
861                margin-bottom: 15px;
862                max-height: 200px;
863                overflow-y: auto;
864            `;
865            
866            // Функция для обновления списка кластерных стратегий
867            const updateClusterList = async () => {
868                const strategies = await getSavedClusterStrategies();
869                const holdPositionStrategyId = await GM.getValue('hold_position_cluster_strategy_id', null);
870                clusterListContainer.innerHTML = '';
871                
872                if (strategies.length === 0) {
873                    const emptyMessage = document.createElement('p');
874                    emptyMessage.textContent = 'Нет сохраненных кластерных стратегий.';
875                    emptyMessage.style.cssText = `
876                        color: #666;
877                        font-style: italic;
878                        padding: 10px;
879                        text-align: center;
880                    `;
881                    clusterListContainer.appendChild(emptyMessage);
882                } else {
883                    strategies.forEach((strategy) => {
884                        const item = document.createElement('div');
885                        const isHoldPosition = strategy.id === holdPositionStrategyId;
886                        item.style.cssText = `
887                            display: flex;
888                            justify-content: space-between;
889                            align-items: center;
890                            padding: 10px;
891                            margin-bottom: 8px;
892                            background: ${isHoldPosition ? '#e8f5e9' : 'white'};
893                            border-radius: 6px;
894                            border: ${isHoldPosition ? '2px solid #4caf50' : '1px solid #ddd'};
895                        `;
896                        
897                        const nameSpan = document.createElement('span');
898                        nameSpan.textContent = strategy.name + (isHoldPosition ? ' ✓' : '');
899                        nameSpan.style.cssText = `
900                            font-size: 14px;
901                            color: #333;
902                            flex: 1;
903                            font-weight: ${isHoldPosition ? 'bold' : 'normal'};
904                        `;
905                        
906                        const selectBtn = document.createElement('button');
907                        selectBtn.textContent = isHoldPosition ? '✓ Выбрана' : 'Выбрать';
908                        selectBtn.disabled = isHoldPosition;
909                        selectBtn.style.cssText = `
910                            background: ${isHoldPosition ? '#4caf50' : '#2196f3'};
911                            color: white;
912                            border: none;
913                            padding: 6px 12px;
914                            border-radius: 6px;
915                            cursor: ${isHoldPosition ? 'default' : 'pointer'};
916                            font-size: 13px;
917                            opacity: ${isHoldPosition ? '0.7' : '1'};
918                        `;
919                        if (!isHoldPosition) {
920                            selectBtn.onmouseover = () => selectBtn.style.background = '#1976d2';
921                            selectBtn.onmouseout = () => selectBtn.style.background = '#2196f3';
922                            selectBtn.onclick = async () => {
923                                await GM.setValue('hold_position_cluster_strategy_id', strategy.id);
924                                console.log(`Установлена кластерная стратегия удержания места: ${strategy.name}`);
925                                await updateClusterList();
926                            };
927                        }
928                        
929                        item.appendChild(nameSpan);
930                        item.appendChild(selectBtn);
931                        clusterListContainer.appendChild(item);
932                    });
933                }
934            };
935            
936            await updateClusterList();
937            clusterSection.appendChild(clusterListContainer);
938            
939            const clusterResetBtn = document.createElement('button');
940            clusterResetBtn.textContent = '🔄 Сбросить на стандартную';
941            clusterResetBtn.style.cssText = `
942                width: 100%;
943                background: #ff9800;
944                color: white;
945                border: none;
946                padding: 10px;
947                border-radius: 6px;
948                cursor: pointer;
949                font-size: 14px;
950                font-weight: 600;
951            `;
952            clusterResetBtn.onmouseover = () => clusterResetBtn.style.background = '#f57c00';
953            clusterResetBtn.onmouseout = () => clusterResetBtn.style.background = '#ff9800';
954            clusterResetBtn.onclick = async () => {
955                await GM.deleteValue('hold_position_cluster_strategy_id');
956                console.log('Кластерная стратегия удержания места сброшена на стандартную');
957                await updateClusterList();
958            };
959            clusterSection.appendChild(clusterResetBtn);
960            
961            modal.appendChild(clusterSection);
962            
963            // Кнопка закрытия
964            const closeButton = document.createElement('button');
965            closeButton.textContent = 'Закрыть';
966            closeButton.style.cssText = `
967                width: 100%;
968                background: #666;
969                color: white;
970                border: none;
971                padding: 12px;
972                border-radius: 8px;
973                cursor: pointer;
974                font-size: 16px;
975            `;
976            closeButton.onmouseover = () => closeButton.style.background = '#555';
977            closeButton.onmouseout = () => closeButton.style.background = '#666';
978            closeButton.onclick = () => {
979                document.body.removeChild(overlay);
980                resolve();
981            };
982            modal.appendChild(closeButton);
983            
984            overlay.appendChild(modal);
985            document.body.appendChild(overlay);
986            
987            // Закрытие по клику на оверлей
988            overlay.onclick = (e) => {
989                if (e.target === overlay) {
990                    document.body.removeChild(overlay);
991                    resolve();
992                }
993            };
994        });
995    }
996
997    // Функция для создания UI
998    function createUI() {
999        console.log('Создание UI панели');
1000        
1001        // Проверяем, есть ли сохраненный ДРР для массовой обработки
1002        GM.getValue('bulkProcessingDRR', null).then(savedDRR => {
1003            if (savedDRR !== null) {
1004                console.log(`Найден сохраненный ДРР для массовой обработки: ${savedDRR}`);
1005                // Автоматически запускаем стратегию с сохраненным ДРР
1006                setTimeout(async () => {
1007                    const input = document.getElementById('desired-percentage');
1008                    if (input) {
1009                        input.value = savedDRR;
1010                        
1011                        // Восстанавливаем состояние чекбоксов из сохраненных настроек
1012                        const savedApplyToClusters = await GM.getValue('bulkApplyToClusters', true);
1013                        const savedHoldPosition = await GM.getValue('bulkHoldPosition', true);
1014                        
1015                        const applyToClustersCheckbox = document.getElementById('apply-to-clusters');
1016                        const holdPositionCheckbox = document.getElementById('hold-position');
1017                        
1018                        if (applyToClustersCheckbox) {
1019                            applyToClustersCheckbox.checked = savedApplyToClusters;
1020                            console.log(`Восстановлено состояние "Применить к кластерам": ${savedApplyToClusters}`);
1021                        }
1022                        
1023                        if (holdPositionCheckbox) {
1024                            holdPositionCheckbox.checked = savedHoldPosition;
1025                            console.log(`Восстановлено состояние "Удержание места": ${savedHoldPosition}`);
1026                        }
1027                        
1028                        // Запускаем стратегию автоматически
1029                        runStrategy();
1030                    }
1031                }, 2000);
1032            }
1033        });
1034        
1035        const panel = document.createElement('div');
1036        panel.id = 'auto-strategy-panel';
1037        panel.style.cssText = `
1038            position: fixed;
1039            top: 20px;
1040            right: 20px;
1041            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
1042            padding: 15px;
1043            border-radius: 12px;
1044            box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
1045            z-index: 10000;
1046            min-width: 280px;
1047            font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
1048            color: white;
1049            transition: all 0.3s ease;
1050            cursor: move;
1051        `;
1052
1053        panel.innerHTML = `
1054            <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 10px; cursor: pointer;" id="panel-header">
1055                <h3 style="margin: 0; font-size: 16px; font-weight: 600;">🚀 Авто-стратегия</h3>
1056                <span id="toggle-icon" style="font-size: 18px;"></span>
1057            </div>
1058            
1059            <div id="panel-content" style="display: none;">
1060                <div style="margin-bottom: 15px;">
1061                    <label style="display: block; margin-bottom: 8px; font-size: 13px; font-weight: 500;">
1062                        Желаемый % рекламных расходов:
1063                    </label>
1064                    <input 
1065                        type="number" 
1066                        id="desired-percentage" 
1067                        value="30" 
1068                        min="1" 
1069                        max="100" 
1070                        step="0.1"
1071                        style="
1072                            width: 100%;
1073                            padding: 10px;
1074                            border: none;
1075                            border-radius: 8px;
1076                            font-size: 14px;
1077                            box-sizing: border-box;
1078                            background: rgba(255, 255, 255, 0.95);
1079                            color: #333;
1080                            cursor: text;
1081                        "
1082                    />
1083                </div>
1084
1085                <div style="margin-bottom: 15px;">
1086                    <label style="display: flex; align-items: center; cursor: pointer; font-size: 13px; font-weight: 500;">
1087                        <input 
1088                            type="checkbox" 
1089                            id="apply-to-clusters" 
1090                            checked
1091                            style="
1092                                margin-right: 8px;
1093                                width: 18px;
1094                                height: 18px;
1095                                cursor: pointer;
1096                            "
1097                        />
1098                        Применить стратегию к кластерам
1099                    </label>
1100                </div>
1101
1102                <div style="margin-bottom: 15px;">
1103                    <label style="display: flex; align-items: center; cursor: pointer; font-size: 13px; font-weight: 500;">
1104                        <input 
1105                            type="checkbox" 
1106                            id="hold-position" 
1107                            checked
1108                            style="
1109                                margin-right: 8px;
1110                                width: 18px;
1111                                height: 18px;
1112                                cursor: pointer;
1113                            "
1114                        />
1115                        Удержание места
1116                    </label>
1117                </div>
1118
1119                <button 
1120                    id="run-strategy-btn"
1121                    style="
1122                        width: 100%;
1123                        padding: 12px;
1124                        background: white;
1125                        color: #667eea;
1126                        border: none;
1127                        border-radius: 8px;
1128                        font-size: 14px;
1129                        font-weight: 600;
1130                        cursor: pointer;
1131                        transition: all 0.3s ease;
1132                        box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
1133                        margin-bottom: 10px;
1134                    "
1135                    onmouseover="this.style.transform='translateY(-2px)'; this.style.boxShadow='0 6px 16px rgba(0, 0, 0, 0.2)';"
1136                    onmouseout="this.style.transform='translateY(0)'; this.style.boxShadow='0 4px 12px rgba(0, 0, 0, 0.15)';"
1137                >
1138                    Запустить
1139                </button>
1140
1141                <button 
1142                    id="manage-strategies-btn"
1143                    style="
1144                        width: 100%;
1145                        padding: 10px;
1146                        background: rgba(255, 255, 255, 0.2);
1147                        color: white;
1148                        border: 1px solid rgba(255, 255, 255, 0.3);
1149                        border-radius: 8px;
1150                        font-size: 13px;
1151                        font-weight: 600;
1152                        cursor: pointer;
1153                        transition: all 0.3s ease;
1154                        margin-bottom: 8px;
1155                    "
1156                    onmouseover="this.style.background='rgba(255, 255, 255, 0.3)';"
1157                    onmouseout="this.style.background='rgba(255, 255, 255, 0.2)';"
1158                >
1159                    ⚙️ Управление стратегиями
1160                </button>
1161
1162                <button 
1163                    id="manage-cluster-strategies-btn"
1164                    style="
1165                        width: 100%;
1166                        padding: 10px;
1167                        background: rgba(255, 255, 255, 0.2);
1168                        color: white;
1169                        border: 1px solid rgba(255, 255, 255, 0.3);
1170                        border-radius: 8px;
1171                        font-size: 13px;
1172                        font-weight: 600;
1173                        cursor: pointer;
1174                        transition: all 0.3s ease;
1175                        margin-bottom: 8px;
1176                    "
1177                    onmouseover="this.style.background='rgba(255, 255, 255, 0.3)';"
1178                    onmouseout="this.style.background='rgba(255, 255, 255, 0.2)';"
1179                >
1180                    🎯 Стратегии для кластеров
1181                </button>
1182
1183                <button 
1184                    id="manage-hold-position-strategies-btn"
1185                    style="
1186                        width: 100%;
1187                        padding: 10px;
1188                        background: rgba(255, 255, 255, 0.2);
1189                        color: white;
1190                        border: 1px solid rgba(255, 255, 255, 0.3);
1191                        border-radius: 8px;
1192                        font-size: 13px;
1193                        font-weight: 600;
1194                        cursor: pointer;
1195                        transition: all 0.3s ease;
1196                    "
1197                    onmouseover="this.style.background='rgba(255, 255, 255, 0.3)';"
1198                    onmouseout="this.style.background='rgba(255, 255, 255, 0.2)';"
1199                >
1200                    📍 Стратегии удержания места
1201                </button>
1202
1203                <div id="status-message" style="
1204                    margin-top: 15px;
1205                    padding: 10px;
1206                    border-radius: 8px;
1207                    font-size: 12px;
1208                    background: rgba(255, 255, 255, 0.2);
1209                    display: none;
1210                "></div>
1211            </div>
1212        `;
1213
1214        document.body.appendChild(panel);
1215        console.log('UI панель создана');
1216
1217        // Добавляем возможность перетаскивания
1218        makeDraggable(panel);
1219
1220        // Добавляем обработчик клика на заголовок для разворачивания/сворачивания
1221        document.getElementById('panel-header').addEventListener('click', () => {
1222            const content = document.getElementById('panel-content');
1223            const icon = document.getElementById('toggle-icon');
1224            if (content.style.display === 'none') {
1225                content.style.display = 'block';
1226                icon.textContent = '▲';
1227            } else {
1228                content.style.display = 'none';
1229                icon.textContent = '▼';
1230            }
1231        });
1232
1233        // Добавляем обработчик клика на кнопку
1234        document.getElementById('run-strategy-btn').addEventListener('click', runStrategy);
1235        
1236        // Добавляем обработчик для кнопки управления стратегиями
1237        document.getElementById('manage-strategies-btn').addEventListener('click', async () => {
1238            await createStrategyManagementModal();
1239        });
1240        
1241        // Добавляем обработчик для кнопки управления кластерными стратегиями
1242        document.getElementById('manage-cluster-strategies-btn').addEventListener('click', async () => {
1243            await createClusterStrategyManagementModal();
1244        });
1245        
1246        // Добавляем обработчик для кнопки управления стратегиями удержания места
1247        document.getElementById('manage-hold-position-strategies-btn').addEventListener('click', async () => {
1248            await createHoldPositionStrategyManagementModal();
1249        });
1250    }
1251
1252    // Функция для создания UI панели массового изменения
1253    function createBulkUI() {
1254        console.log('Создание UI панели массового изменения');
1255        
1256        const panel = document.createElement('div');
1257        panel.id = 'bulk-strategy-panel';
1258        panel.style.cssText = `
1259            position: fixed;
1260            top: 20px;
1261            right: 20px;
1262            background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);
1263            padding: 15px;
1264            border-radius: 12px;
1265            box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
1266            z-index: 10000;
1267            min-width: 300px;
1268            font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
1269            color: white;
1270            transition: all 0.3s ease;
1271            cursor: move;
1272        `;
1273
1274        panel.innerHTML = `
1275            <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 10px; cursor: pointer;" id="bulk-panel-header">
1276                <h3 style="margin: 0; font-size: 16px; font-weight: 600;">📦 Массовое изменение</h3>
1277                <span id="bulk-toggle-icon" style="font-size: 18px;"></span>
1278            </div>
1279            
1280            <div id="bulk-panel-content" style="display: none;">
1281                <div style="margin-bottom: 15px;">
1282                    <label style="display: block; margin-bottom: 8px; font-size: 13px; font-weight: 500;">
1283                        Желаемый % рекламных расходов (ДРР):
1284                    </label>
1285                    <input 
1286                        type="number" 
1287                        id="bulk-desired-percentage" 
1288                        value="30" 
1289                        min="1" 
1290                        max="100" 
1291                        step="0.1"
1292                        style="
1293                            width: 100%;
1294                            padding: 10px;
1295                            border: none;
1296                            border-radius: 8px;
1297                            font-size: 14px;
1298                            box-sizing: border-box;
1299                            background: rgba(255, 255, 255, 0.95);
1300                            color: #333;
1301                            cursor: text;
1302                        "
1303                    />
1304                </div>
1305
1306                <div id="bulk-campaigns-info" style="
1307                    margin-bottom: 15px;
1308                    padding: 10px;
1309                    border-radius: 8px;
1310                    font-size: 12px;
1311                    background: rgba(255, 255, 255, 0.2);
1312                ">
1313                    Найдено кампаний: <span id="campaigns-count">0</span>
1314                </div>
1315
1316                <button 
1317                    id="run-bulk-strategy-btn"
1318                    style="
1319                        width: 100%;
1320                        padding: 12px;
1321                        background: white;
1322                        color: #f5576c;
1323                        border: none;
1324                        border-radius: 8px;
1325                        font-size: 14px;
1326                        font-weight: 600;
1327                        cursor: pointer;
1328                        transition: all 0.3s ease;
1329                        box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
1330                        margin-bottom: 10px;
1331                    "
1332                    onmouseover="this.style.transform='translateY(-2px)'; this.style.boxShadow='0 6px 16px rgba(0, 0, 0, 0.2)';"
1333                    onmouseout="this.style.transform='translateY(0)'; this.style.boxShadow='0 4px 12px rgba(0, 0, 0, 0.15)';"
1334                >
1335                    Запустить
1336                </button>
1337
1338                <button 
1339                    id="bulk-manage-strategies-btn"
1340                    style="
1341                        width: 100%;
1342                        padding: 10px;
1343                        background: rgba(255, 255, 255, 0.2);
1344                        color: white;
1345                        border: 1px solid rgba(255, 255, 255, 0.3);
1346                        border-radius: 8px;
1347                        font-size: 13px;
1348                        font-weight: 600;
1349                        cursor: pointer;
1350                        transition: all 0.3s ease;
1351                        margin-bottom: 10px;
1352                    "
1353                    onmouseover="this.style.background='rgba(255, 255, 255, 0.3)';"
1354                    onmouseout="this.style.background='rgba(255, 255, 255, 0.2)';"
1355                >
1356                    ⚙️ Управление стратегиями
1357                </button>
1358
1359                <button 
1360                    id="bulk-manage-cluster-strategies-btn"
1361                    style="
1362                        width: 100%;
1363                        padding: 10px;
1364                        background: rgba(255, 255, 255, 0.2);
1365                        color: white;
1366                        border: 1px solid rgba(255, 255, 255, 0.3);
1367                        border-radius: 8px;
1368                        font-size: 13px;
1369                        font-weight: 600;
1370                        cursor: pointer;
1371                        transition: all 0.3s ease;
1372                        margin-bottom: 10px;
1373                    "
1374                    onmouseover="this.style.background='rgba(255, 255, 255, 0.3)';"
1375                    onmouseout="this.style.background='rgba(255, 255, 255, 0.2)';"
1376                >
1377                    🎯 Стратегии для кластеров
1378                </button>
1379
1380                <div style="margin-bottom: 15px;">
1381                    <label style="display: flex; align-items: center; cursor: pointer; font-size: 13px; font-weight: 500;">
1382                        <input 
1383                            type="checkbox" 
1384                            id="bulk-apply-to-clusters" 
1385                            checked
1386                            style="
1387                                margin-right: 8px;
1388                                width: 18px;
1389                                height: 18px;
1390                                cursor: pointer;
1391                            "
1392                        />
1393                        Применить стратегию к кластерам
1394                    </label>
1395                </div>
1396
1397                <div style="margin-bottom: 15px;">
1398                    <label style="display: flex; align-items: center; cursor: pointer; font-size: 13px; font-weight: 500;">
1399                        <input 
1400                            type="checkbox" 
1401                            id="bulk-hold-position" 
1402                            checked
1403                            style="
1404                                margin-right: 8px;
1405                                width: 18px;
1406                                height: 18px;
1407                                cursor: pointer;
1408                            "
1409                        />
1410                        Удержание места
1411                    </label>
1412                </div>
1413
1414                <div id="bulk-control-buttons" style="
1415                    margin-top: 10px;
1416                    display: none;
1417                    gap: 10px;
1418                ">
1419                    <button 
1420                        id="pause-bulk-btn"
1421                        style="
1422                            flex: 1;
1423                            padding: 10px;
1424                            background: rgba(255, 255, 255, 0.9);
1425                            color: #f5576c;
1426                            border: none;
1427                            border-radius: 8px;
1428                            font-size: 13px;
1429                            font-weight: 600;
1430                            cursor: pointer;
1431                            transition: all 0.3s ease;
1432                        "
1433                    >
1434                        ⏏️ Пауза
1435                    </button>
1436                    <button 
1437                        id="stop-bulk-btn"
1438                        style="
1439                            flex: 1;
1440                            padding: 10px;
1441                            background: rgba(255, 59, 48, 0.9);
1442                            color: white;
1443                            border: none;
1444                            border-radius: 8px;
1445                            font-size: 13px;
1446                            font-weight: 600;
1447                            cursor: pointer;
1448                            transition: all 0.3s ease;
1449                        "
1450                    >
1451                        ⏹️ Стоп
1452                    </button>
1453                </div>
1454
1455                <div id="bulk-status-message" style="
1456                    margin-top: 15px;
1457                    padding: 10px;
1458                    border-radius: 8px;
1459                    font-size: 12px;
1460                    background: rgba(255, 255, 255, 0.2);
1461                    display: none;
1462                "></div>
1463
1464                <div id="bulk-progress" style="
1465                    margin-top: 15px;
1466                    display: none;
1467                ">
1468                    <div style="margin-bottom: 5px; font-size: 12px;">
1469                        Прогресс: <span id="bulk-progress-text">0/0</span>
1470                    </div>
1471                    <div style="
1472                        width: 100%;
1473                        height: 8px;
1474                        background: rgba(255, 255, 255, 0.3);
1475                        border-radius: 4px;
1476                        overflow: hidden;
1477                    ">
1478                        <div id="bulk-progress-bar" style="
1479                            width: 0%;
1480                            height: 100%;
1481                            background: white;
1482                            transition: width 0.3s ease;
1483                        "></div>
1484                    </div>
1485                </div>
1486            </div>
1487        `;
1488
1489        document.body.appendChild(panel);
1490        console.log('UI панель массового изменения создана');
1491
1492        // Добавляем возможность перетаскивания
1493        makeDraggable(panel);
1494
1495        // Подсчитываем количество кампаний
1496        updateCampaignsCount();
1497
1498        // Добавляем обработчик клика на заголовок для разворачивания/сворачивания
1499        document.getElementById('bulk-panel-header').addEventListener('click', () => {
1500            const content = document.getElementById('bulk-panel-content');
1501            const icon = document.getElementById('bulk-toggle-icon');
1502            if (content.style.display === 'none') {
1503                content.style.display = 'block';
1504                icon.textContent = '▲';
1505            } else {
1506                content.style.display = 'none';
1507                icon.textContent = '▼';
1508            }
1509        });
1510
1511        // Добавляем обработчик клика на кнопку
1512        document.getElementById('run-bulk-strategy-btn').addEventListener('click', runBulkStrategy);
1513        
1514        // Добавляем обработчик для кнопки управления стратегиями
1515        document.getElementById('bulk-manage-strategies-btn').addEventListener('click', async () => {
1516            await createStrategyManagementModal();
1517        });
1518        
1519        // Добавляем обработчик для кнопки управления кластерными стратегиями
1520        document.getElementById('bulk-manage-cluster-strategies-btn').addEventListener('click', async () => {
1521            await createClusterStrategyManagementModal();
1522        });
1523        
1524        // Добавляем обработчики для кнопок управления
1525        document.getElementById('pause-bulk-btn').addEventListener('click', pauseBulkProcessing);
1526        document.getElementById('stop-bulk-btn').addEventListener('click', stopBulkProcessing);
1527    }
1528
1529    // Функция для создания перетаскиваемого элемента
1530    function makeDraggable(element) {
1531        let pos1 = 0, pos2 = 0, pos3 = 0, pos4 = 0;
1532        let isDragging = false;
1533
1534        element.onmousedown = dragMouseDown;
1535
1536        function dragMouseDown(e) {
1537            // Не перетаскиваем, если кликнули на input, button или другие интерактивные элементы
1538            if (e.target.tagName === 'INPUT' || e.target.tagName === 'BUTTON' || e.target.tagName === 'TEXTAREA') {
1539                return;
1540            }
1541            
1542            e.preventDefault();
1543            isDragging = true;
1544            pos3 = e.clientX;
1545            pos4 = e.clientY;
1546            document.onmouseup = closeDragElement;
1547            document.onmousemove = elementDrag;
1548        }
1549
1550        function elementDrag(e) {
1551            if (!isDragging) return;
1552            pos1 = pos3 - e.clientX;
1553            pos2 = pos4 - e.clientY;
1554            pos3 = e.clientX;
1555            pos4 = e.clientY;
1556            element.style.top = (element.offsetTop - pos2) + 'px';
1557            element.style.left = (element.offsetLeft - pos1) + 'px';
1558            element.style.right = 'auto';
1559            element.style.bottom = 'auto';
1560        }
1561
1562        function closeDragElement() {
1563            isDragging = false;
1564            document.onmouseup = null;
1565            document.onmousemove = null;
1566        }
1567    }
1568
1569    // Функция для обновления количества кампаний
1570    function updateCampaignsCount() {
1571        const campaignLinks = document.querySelectorAll('a[href*="/campaigns/auto-campaigns/"][href*="/campaign"]');
1572        const count = campaignLinks.length;
1573        const countElement = document.getElementById('campaigns-count');
1574        if (countElement) {
1575            countElement.textContent = count;
1576        }
1577        console.log(`Найдено кампаний: ${count}`);
1578    }
1579
1580    // Функция для показа статуса массовой обработки
1581    function showBulkStatus(message, isError = false) {
1582        const statusDiv = document.getElementById('bulk-status-message');
1583        if (statusDiv) {
1584            statusDiv.textContent = message;
1585            statusDiv.style.display = 'block';
1586            statusDiv.style.background = isError ? 'rgba(255, 59, 48, 0.9)' : 'rgba(52, 199, 89, 0.9)';
1587            console.log(`Статус массовой обработки: ${message}`);
1588        }
1589    }
1590
1591    // Функция для обновления прогресса
1592    function updateBulkProgress(current, total) {
1593        const progressDiv = document.getElementById('bulk-progress');
1594        const progressText = document.getElementById('bulk-progress-text');
1595        const progressBar = document.getElementById('bulk-progress-bar');
1596        
1597        if (progressDiv && progressText && progressBar) {
1598            progressDiv.style.display = 'block';
1599            progressText.textContent = `${current}/${total}`;
1600            const percentage = (current / total) * 100;
1601            progressBar.style.width = `${percentage}%`;
1602        }
1603    }
1604
1605    // Функция для прокрутки страницы вниз для загрузки всех кампаний
1606    async function scrollToLoadAllCampaigns() {
1607        console.log('Начинаем загрузку всех кампаний через прокрутку...');
1608        
1609        // Находим контейнер с прокруткой
1610        const tableContainer = document.querySelector('.container.MuiBox-root.css-9hf803');
1611        
1612        if (!tableContainer) {
1613            console.error('Контейнер таблицы не найден');
1614            return [];
1615        }
1616        
1617        console.log('Контейнер найден, начинаем прокрутку...');
1618        console.log(`Высота контейнера: ${tableContainer.scrollHeight}px`);
1619        
1620        // Собираем уникальные ссылки во время прокрутки
1621        const uniqueLinks = new Set();
1622        
1623        // Прокручиваем контейнер постепенно, чтобы загрузить все кампании
1624        let previousLinksCount = 0;
1625        let stableCount = 0;
1626        const maxAttempts = 200; // Максимум попыток
1627        let attempts = 0;
1628        const scrollStep = 500; // Прокручиваем по 500px за раз
1629        
1630        while (attempts < maxAttempts) {
1631            // Собираем ссылки на текущем шаге
1632            const currentLinks = document.querySelectorAll('a[href*="/campaigns/auto-campaigns/"][href*="/campaign"]');
1633            currentLinks.forEach(link => {
1634                uniqueLinks.add(link.href);
1635            });
1636            
1637            const currentCount = uniqueLinks.size;
1638            console.log(`Загружено кампаний: ${currentCount}, прокрутка: ${tableContainer.scrollTop}/${tableContainer.scrollHeight}`);
1639            
1640            // Прокручиваем контейнер постепенно
1641            tableContainer.scrollTop += scrollStep;
1642            
1643            // Ждем загрузки новых элементов
1644            await wait(500);
1645            
1646            // Если количество не изменилось
1647            if (currentCount === previousLinksCount) {
1648                stableCount++;
1649                // Если количество стабильно 5 раз подряд - значит все загружено
1650                if (stableCount >= 5) {
1651                    console.log('Все кампании загружены');
1652                    break;
1653                }
1654            } else {
1655                stableCount = 0;
1656                previousLinksCount = currentCount;
1657            }
1658            
1659            // Если достигли конца контейнера
1660            if (tableContainer.scrollTop + tableContainer.clientHeight >= tableContainer.scrollHeight - 10) {
1661                console.log('Достигнут конец контейнера');
1662                // Ждем еще немного для загрузки последних элементов
1663                await wait(1000);
1664                
1665                // Собираем последние ссылки
1666                const finalLinks = document.querySelectorAll('a[href*="/campaigns/auto-campaigns/"][href*="/campaign"]');
1667                finalLinks.forEach(link => {
1668                    uniqueLinks.add(link.href);
1669                });
1670                
1671                // Проверяем еще раз количество
1672                if (uniqueLinks.size === previousLinksCount) {
1673                    break;
1674                }
1675                previousLinksCount = uniqueLinks.size;
1676            }
1677            
1678            attempts++;
1679        }
1680        
1681        // Преобразуем Set в массив URL (НЕ прокручиваем обратно!)
1682        const links = Array.from(uniqueLinks);
1683        
1684        console.log(`Найдено кампаний: ${links.length}`);
1685        console.log(`Всего попыток прокрутки: ${attempts}`);
1686        return links;
1687    }
1688
1689    // Функция для массовой обработки кампаний
1690    async function runBulkStrategy() {
1691        if (isBulkProcessing) {
1692            showBulkStatus('Обработка уже выполняется', true);
1693            return;
1694        }
1695
1696        try {
1697            isBulkProcessing = true;
1698            console.log('Начало массовой обработки кампаний');
1699            
1700            bulkDesiredPercentage = parseFloat(document.getElementById('bulk-desired-percentage').value);
1701            if (!bulkDesiredPercentage || bulkDesiredPercentage <= 0) {
1702                showBulkStatus('Ошибка: введите корректный процент', true);
1703                isBulkProcessing = false;
1704                return;
1705            }
1706            console.log(`Желаемый процент: ${bulkDesiredPercentage}%`);
1707
1708            // Сохраняем ДРР для автоматической обработки
1709            await GM.setValue('bulkProcessingDRR', bulkDesiredPercentage);
1710            console.log(`ДРР ${bulkDesiredPercentage} сохранен для массовой обработки`);
1711            
1712            // Сохраняем состояние чекбоксов
1713            const applyToClustersCheckbox = document.getElementById('bulk-apply-to-clusters');
1714            const holdPositionCheckbox = document.getElementById('bulk-hold-position');
1715            
1716            if (applyToClustersCheckbox) {
1717                await GM.setValue('bulkApplyToClusters', applyToClustersCheckbox.checked);
1718                console.log(`Сохранено состояние "Применить к кластерам": ${applyToClustersCheckbox.checked}`);
1719            }
1720            
1721            if (holdPositionCheckbox) {
1722                await GM.setValue('bulkHoldPosition', holdPositionCheckbox.checked);
1723                console.log(`Сохранено состояние "Удержание места": ${holdPositionCheckbox.checked}`);
1724            }
1725
1726            // Прокручиваем страницу для загрузки всех кампаний
1727            const campaignLinks = await scrollToLoadAllCampaigns();
1728            
1729            if (campaignLinks.length === 0) {
1730                showBulkStatus('Ошибка: кампании не найдены', true);
1731                isBulkProcessing = false;
1732                await GM.deleteValue('bulkProcessingDRR');
1733                return;
1734            }
1735
1736            console.log(`Найдено кампаний для обработки: ${campaignLinks.length}`);
1737            showBulkStatus(`Начинаем обработку ${campaignLinks.length} кампаний...`);
1738            updateBulkProgress(0, campaignLinks.length);
1739
1740            // Сохраняем список кампаний (массив URL), текущий индекс и общее количество
1741            await GM.setValue('bulkCampaigns', JSON.stringify(campaignLinks));
1742            await GM.setValue('bulkCurrentIndex', 0);
1743            await GM.setValue('bulkTotalCampaigns', campaignLinks.length);
1744
1745            // Показываем кнопки управления
1746            const controlButtons = document.getElementById('bulk-control-buttons');
1747            if (controlButtons) {
1748                controlButtons.style.display = 'flex';
1749            }
1750
1751            // Открываем первую кампанию в новой вкладке через window.open
1752            if (campaignLinks.length > 0) {
1753                console.log(`Открытие кампании 1/${campaignLinks.length}: ${campaignLinks[0]}`);
1754                window.open(campaignLinks[0], '_blank');
1755            }
1756
1757        } catch (error) {
1758            console.error('Ошибка при массовой обработке:', error);
1759            showBulkStatus(`Ошибка: ${error.message}`, true);
1760            isBulkProcessing = false;
1761            await GM.deleteValue('bulkProcessingDRR');
1762        }
1763    }
1764
1765    // Функция для паузы массовой обработки
1766    async function pauseBulkProcessing() {
1767        bulkPaused = !bulkPaused;
1768        const pauseBtn = document.getElementById('pause-bulk-btn');
1769        
1770        if (bulkPaused) {
1771            await GM.setValue('bulkPaused', true);
1772            pauseBtn.textContent = '▶️ Продолжить';
1773            showBulkStatus('⏸️ Обработка приостановлена');
1774            console.log('Массовая обработка приостановлена');
1775        } else {
1776            await GM.deleteValue('bulkPaused');
1777            pauseBtn.textContent = '⏸️ Пауза';
1778            showBulkStatus('▶️ Обработка возобновлена');
1779            console.log('Массовая обработка возобновлена');
1780            
1781            // Продолжаем обработку - открываем следующую кампанию
1782            const campaignsJson = await GM.getValue('bulkCampaigns', null);
1783            const currentIndex = await GM.getValue('bulkCurrentIndex', 0);
1784            const totalCampaigns = await GM.getValue('bulkTotalCampaigns', 0);
1785            
1786            if (campaignsJson) {
1787                const campaigns = JSON.parse(campaignsJson);
1788                const nextIndex = currentIndex + 1;
1789                
1790                console.log(`Обработано кампаний: ${nextIndex} из ${totalCampaigns}`);
1791                
1792                if (nextIndex < campaigns.length) {
1793                    // Сохраняем новый индекс
1794                    await GM.setValue('bulkCurrentIndex', nextIndex);
1795                    
1796                    // Открываем следующую кампанию в новой вкладке через window.open
1797                    console.log(`Открываем кампанию ${nextIndex + 1}: ${campaigns[nextIndex]}`);
1798                    const newTab = window.open(campaigns[nextIndex], '_blank');
1799                    
1800                    if (newTab) {
1801                        // Закрываем текущую вкладку
1802                        await wait(1000);
1803                        window.close();
1804                    } else {
1805                        // Если блокировщик всплывающих окон, используем редирект
1806                        console.log('Блокировщик всплывающих окон, используем редирект');
1807                        window.location.href = campaigns[nextIndex];
1808                    }
1809                }
1810            }
1811        }
1812    }
1813
1814    // Функция для остановки массовой обработки
1815    async function stopBulkProcessing() {
1816        await GM.deleteValue('bulkProcessingDRR');
1817        await GM.deleteValue('bulkCampaigns');
1818        await GM.deleteValue('bulkCurrentIndex');
1819        await GM.deleteValue('bulkTotalCampaigns');
1820        
1821        showBulkStatus('⏹️ Обработка остановлена', true);
1822        console.log('Массовая обработка остановлена');
1823        
1824        // Скрываем кнопки управления
1825        const controlButtons = document.getElementById('bulk-control-buttons');
1826        if (controlButtons) {
1827            controlButtons.style.display = 'none';
1828        }
1829        
1830        isBulkProcessing = false;
1831        bulkPaused = false;
1832    }
1833
1834    // Функция для показа статуса
1835    function showStatus(message, isError = false) {
1836        const statusDiv = document.getElementById('status-message');
1837        if (statusDiv) {
1838            statusDiv.textContent = message;
1839            statusDiv.style.display = 'block';
1840            statusDiv.style.background = isError ? 'rgba(255, 59, 48, 0.9)' : 'rgba(52, 199, 89, 0.9)';
1841            console.log(`Статус: ${message}`);
1842        }
1843    }
1844
1845    // Функция для ожидания
1846    function wait(ms) {
1847        return new Promise(resolve => setTimeout(resolve, ms));
1848    }
1849
1850    // Функция для парсинга числа из строки
1851    function parseNumber(str) {
1852        if (!str) return 0;
1853        // Убираем все символы кроме цифр, точек и запятых
1854        const cleaned = str.replace(/[^\d.,]/g, '').replace(/\s/g, '');
1855        // Заменяем запятую на точку
1856        const normalized = cleaned.replace(',', '.');
1857        return parseFloat(normalized) || 0;
1858    }
1859
1860    // Функция для парсинга процента
1861    function parsePercentage(str) {
1862        if (!str) return 0;
1863        const cleaned = str.replace('%', '').replace(',', '.').trim();
1864        return parseFloat(cleaned) || 0;
1865    }
1866
1867    // Основная функция запуска стратегии
1868    async function runStrategy() {
1869        try {
1870            console.log('Начало выполнения стратегии');
1871            showStatus('Запуск процесса...');
1872
1873            const desiredPercentage = parseFloat(document.getElementById('desired-percentage').value);
1874            if (!desiredPercentage || desiredPercentage <= 0) {
1875                showStatus('Ошибка: введите корректный процент', true);
1876                await handleStrategyError();
1877                return;
1878            }
1879            console.log(`Желаемый процент: ${desiredPercentage}%`);
1880
1881            // Проверяем чекбоксы из обеих панелей
1882            const holdPositionCheckbox = document.getElementById('hold-position');
1883            const bulkHoldPositionCheckbox = document.getElementById('bulk-hold-position');
1884            const shouldApplyHoldPosition = holdPositionCheckbox ? holdPositionCheckbox.checked : 
1885                (bulkHoldPositionCheckbox ? bulkHoldPositionCheckbox.checked : false);
1886
1887            // Шаг 1: Кликаем на статистику
1888            showStatus('Открытие статистики...');
1889            const statsButton = document.querySelector('.css-amj7dw');
1890            if (!statsButton) {
1891                showStatus('Ошибка: кнопка статистики не найдена', true);
1892                await handleStrategyError();
1893                return;
1894            }
1895            statsButton.click();
1896            console.log('Клик на статистику выполнен');
1897            await wait(2000);
1898
1899            // Шаг 1.5: Выбираем режим "Товары"
1900            showStatus('Выбор режима "Товары"...');
1901            const modeLabels = Array.from(document.querySelectorAll('label'));
1902            let modeInput = null;
1903            
1904            for (const label of modeLabels) {
1905                if (label.textContent.trim() === 'Режим') {
1906                    const inputId = label.getAttribute('for');
1907                    if (inputId) {
1908                        modeInput = document.getElementById(inputId);
1909                        console.log(`Найдено поле Режим с id: ${inputId}`);
1910                        break;
1911                    }
1912                }
1913            }
1914            
1915            if (modeInput) {
1916                modeInput.value = 'Товары';
1917                const inputEvent = new Event('input', { bubbles: true });
1918                const changeEvent = new Event('change', { bubbles: true });
1919                modeInput.dispatchEvent(inputEvent);
1920                modeInput.dispatchEvent(changeEvent);
1921                
1922                console.log('Установлено значение: Товары');
1923                await wait(1000);
1924                
1925                const options = document.querySelectorAll('[role="option"]');
1926                console.log(`Найдено опций: ${options.length}`);
1927                
1928                if (options.length > 0) {
1929                    const tovarOption = Array.from(options).find(opt => opt.textContent.includes('Товары'));
1930                    if (tovarOption) {
1931                        tovarOption.click();
1932                        console.log('Выбран режим "Товары"');
1933                        await wait(1000);
1934                    }
1935                }
1936            }
1937
1938            // Шаг 2: Извлекаем данные из статистики
1939            showStatus('Извлечение данных...');
1940            await wait(500);
1941            
1942            const stats = Array.from(document.querySelectorAll('.MuiTypography-caption.css-1et52kr'));
1943            
1944            let sumOrders = 0;
1945            let ordersCount = 0;
1946            let cartToOrderPercent = 0;
1947
1948            stats.forEach(el => {
1949                const text = el.textContent.trim();
1950                const valueElement = el.closest('.MuiBox-root')?.querySelector('.MuiTypography-h3 .MuiTypography-body1');
1951                const value = valueElement ? valueElement.textContent.trim() : '';
1952
1953                console.log(`Найден показатель: ${text} = ${value}`);
1954
1955                if (text === 'Сумма заказов') {
1956                    sumOrders = parseNumber(value);
1957                    console.log(`Сумма заказов: ${sumOrders}`);
1958                } else if (text === 'Заказов') {
1959                    ordersCount = parseNumber(value);
1960                    console.log(`Заказов: ${ordersCount}`);
1961                } else if (text === 'Корзина → Заказ') {
1962                    cartToOrderPercent = parsePercentage(value);
1963                    console.log(`Корзина → Заказ: ${cartToOrderPercent}%`);
1964                }
1965            });
1966
1967            if (sumOrders === 0 || ordersCount === 0 || cartToOrderPercent === 0) {
1968                showStatus('Ошибка: не удалось получить данные статистики', true);
1969                console.error('Недостаточно данных:', { sumOrders, ordersCount, cartToOrderPercent });
1970                await handleStrategyError();
1971                return;
1972            }
1973
1974            // Шаг 3: Вычисляем стоимость корзины
1975            const cartCost = (sumOrders / ordersCount) * (desiredPercentage / 100) * (cartToOrderPercent / 100);
1976            const cartCostRounded = Math.round(cartCost * 100) / 100;
1977            console.log(`Расчет: (${sumOrders} / ${ordersCount}) * (${desiredPercentage} / 100) * (${cartToOrderPercent} / 100) = ${cartCostRounded}`);
1978            showStatus(`Рассчитано: ${cartCostRounded}`);
1979
1980            // Закрываем статистику
1981            statsButton.click();
1982            await wait(500);
1983
1984            // Шаг 4: Кликаем на "Вставить стратегию"
1985            showStatus('Вставка стратегии...');
1986            const insertButtons = document.querySelectorAll('.css-5kbhos');
1987            let insertButton = null;
1988            
1989            for (const btn of insertButtons) {
1990                if (btn.textContent.includes('Вставить стратегию')) {
1991                    insertButton = btn;
1992                    break;
1993                }
1994            }
1995
1996            if (!insertButton && insertButtons.length >= 2) {
1997                insertButton = insertButtons[1];
1998            } else if (!insertButton && insertButtons.length === 1) {
1999                insertButton = insertButtons[0];
2000            }
2001
2002            if (!insertButton) {
2003                showStatus('Ошибка: кнопка "Вставить стратегию" не найдена', true);
2004                await handleStrategyError();
2005                return;
2006            }
2007
2008            // Получаем текущую выбранную стратегию
2009            let currentStrategyCode;
2010            if (shouldApplyHoldPosition) {
2011                currentStrategyCode = await getHoldPositionStrategy();
2012                console.log('Используем стратегию удержания места, длина:', currentStrategyCode.length);
2013            } else {
2014                currentStrategyCode = await getCurrentStrategy();
2015                console.log('Используем обычную стратегию, длина:', currentStrategyCode.length);
2016            }
2017            
2018            // Копируем код стратегии в буфер обмена
2019            console.log('Копируем стратегию в буфер обмена...');
2020            
2021            try {
2022                await navigator.clipboard.writeText(currentStrategyCode);
2023                console.log('✓ Стратегия скопирована через navigator.clipboard');
2024            } catch {
2025                console.log('navigator.clipboard не сработал, пробуем GM.setClipboard...');
2026                try {
2027                    await GM.setClipboard(currentStrategyCode);
2028                    console.log('✓ Стратегия скопирована через GM.setClipboard');
2029                } catch (e2) {
2030                    console.error('Ошибка копирования через GM.setClipboard:', e2.message);
2031                }
2032            }
2033            
2034            await wait(500);
2035
2036            insertButton.click();
2037            console.log('Клик на "Вставить стратегию" выполнен');
2038            await wait(500);
2039            
2040            console.log('✓ Стратегия вставлена из буфера обмена');
2041            await wait(500);
2042
2043            // Шаг 5: Находим поле "Желаемое значение" и вставляем результат
2044            showStatus('Заполнение поля...');
2045            
2046            const inputLabels = Array.from(document.querySelectorAll('.MuiInputLabel-root'));
2047            let targetInput = null;
2048
2049            for (const label of inputLabels) {
2050                const labelText = label.textContent;
2051                if (labelText.includes('Желаемое значение За корзину')) {
2052                    const inputId = label.getAttribute('for');
2053                    if (inputId) {
2054                        targetInput = document.getElementById(inputId);
2055                        console.log(`Найдено поле: ${labelText}, id: ${inputId}`);
2056                        break;
2057                    }
2058                }
2059            }
2060
2061            if (!targetInput) {
2062                const inputs = document.querySelectorAll('input[type="number"]');
2063                for (const input of inputs) {
2064                    const name = input.getAttribute('name') || '';
2065                    if (name.includes('rules') && name.includes('value')) {
2066                        targetInput = input;
2067                        console.log(`Найдено поле по имени: ${name}`);
2068                        break;
2069                    }
2070                }
2071            }
2072
2073            if (!targetInput) {
2074                showStatus('Ошибка: поле для ввода не найдено', true);
2075                console.error('Не удалось найти поле для ввода значения');
2076                await handleStrategyError();
2077                return;
2078            }
2079
2080            targetInput.focus();
2081            targetInput.value = cartCostRounded.toString();
2082            
2083            const inputEvent = new Event('input', { bubbles: true });
2084            const changeEvent = new Event('change', { bubbles: true });
2085            targetInput.dispatchEvent(inputEvent);
2086            targetInput.dispatchEvent(changeEvent);
2087            
2088            console.log(`Значение ${cartCostRounded} установлено в поле ${targetInput.id}`);
2089            await wait(500);
2090
2091            // Шаг 6: Нажимаем "Сохранить"
2092            showStatus('Сохранение...');
2093            const saveButtons = document.querySelectorAll('button');
2094            let saveButton = null;
2095
2096            for (const btn of saveButtons) {
2097                if (btn.textContent.trim() === 'Сохранить') {
2098                    saveButton = btn;
2099                    break;
2100                }
2101            }
2102
2103            if (!saveButton) {
2104                showStatus('Ошибка: кнопка "Сохранить" не найдена', true);
2105                await handleStrategyError();
2106                return;
2107            }
2108
2109            saveButton.click();
2110            console.log('Клик на "Сохранить" выполнен');
2111            await wait(500);
2112
2113            showStatus(`✅ Готово! Стоимость корзины: ${cartCostRounded}`);
2114            console.log('Стратегия успешно установлена');
2115
2116            // Шаг 7: Работа с кластерами
2117            // Проверяем чекбоксы из обеих панелей
2118            const applyToClusters = document.getElementById('apply-to-clusters');
2119            const bulkApplyToClusters = document.getElementById('bulk-apply-to-clusters');
2120            const shouldApplyToClusters = applyToClusters ? applyToClusters.checked : 
2121                (bulkApplyToClusters ? bulkApplyToClusters.checked : true);
2122            
2123            if (!shouldApplyToClusters) {
2124                console.log('Применение стратегии к кластерам отключено');
2125                showStatus('✅ Готово! Кластеры пропущены');
2126                
2127                // Проверяем, идет ли массовая обработка
2128                const savedDRR = await GM.getValue('bulkProcessingDRR', null);
2129                if (savedDRR !== null) {
2130                    console.log('Массовая обработка: переход к следующей кампании');
2131                    await wait(2000);
2132                    
2133                    const campaignsJson = await GM.getValue('bulkCampaigns', null);
2134                    const currentIndex = await GM.getValue('bulkCurrentIndex', 0);
2135                    const totalCampaigns = await GM.getValue('bulkTotalCampaigns', 0);
2136                    
2137                    if (campaignsJson) {
2138                        const campaigns = JSON.parse(campaignsJson);
2139                        const nextIndex = currentIndex + 1;
2140                        
2141                        console.log(`Обработано кампаний: ${nextIndex} из ${totalCampaigns}`);
2142                        
2143                        if (nextIndex < campaigns.length) {
2144                            await GM.setValue('bulkCurrentIndex', nextIndex);
2145                            console.log(`Переходим к кампании ${nextIndex + 1}: ${campaigns[nextIndex]}`);
2146                            window.location.href = campaigns[nextIndex];
2147                        } else {
2148                            console.log('Все кампании обработаны');
2149                            await GM.deleteValue('bulkProcessingDRR');
2150                            await GM.deleteValue('bulkCampaigns');
2151                            await GM.deleteValue('bulkCurrentIndex');
2152                            await GM.deleteValue('bulkTotalCampaigns');
2153                            
2154                            showStatus('✅ Все кампании обработаны!');
2155                            alert('✅ Все кампании обработаны!');
2156                        }
2157                    }
2158                }
2159                return;
2160            }
2161
2162            console.log('Применение стратегии к кластерам включено');
2163            
2164            // Переходим во вкладку "Кластеры"
2165            const tabs = Array.from(document.querySelectorAll('button[role="tab"]'));
2166            const clustersTab = tabs.find(tab => tab.textContent.trim() === 'Кластеры');
2167            if (!clustersTab) {
2168                console.error('Вкладка "Кластеры" не найдена');
2169                showStatus('⚠️ Вкладка "Кластеры" не найдена', true);
2170                return;
2171            }
2172
2173            clustersTab.click();
2174            console.log('Клик на "Кластеры" выполнен');
2175            await wait(1000);
2176            
2177            // Ждем загрузки кластеров
2178            let loadingAttempts = 0;
2179            while (loadingAttempts < 10) {
2180                const skeleton = document.querySelector('.MuiSkeleton-root');
2181                if (!skeleton) {
2182                    console.log('Кластеры загружены');
2183                    break;
2184                }
2185                console.log(`Ожидание загрузки кластеров, попытка ${loadingAttempts + 1}`);
2186                await wait(500);
2187                loadingAttempts++;
2188            }
2189            
2190            // СНАЧАЛА применяем обычную стратегию ко ВСЕМ кластерам
2191            showStatus('Применение обычной стратегии ко всем кластерам...');
2192            console.log('Шаг 1: Применяем обычную стратегию ко всем кластерам');
2193            
2194            // Выделяем отфильтрованные кластеры
2195            showStatus('Выделение отфильтрованных кластеров...');
2196            
2197            // Сначала кликаем на первый чекбокс в списке кластеров
2198            const firstClusterCheckbox = document.querySelector('tbody input[type="checkbox"]');
2199            if (firstClusterCheckbox) {
2200                firstClusterCheckbox.click();
2201                console.log('Клик на первый чекбокс кластера выполнен');
2202                await wait(500);
2203            }
2204            
2205            // Теперь кликаем на общий чекбокс для выделения всех
2206            let selectAllCheckbox2 = document.querySelector('.css-1ytbthu .css-vlug8u');
2207            if (!selectAllCheckbox2) {
2208                selectAllCheckbox2 = document.querySelector('thead .css-vlug8u');
2209            }
2210            if (!selectAllCheckbox2) {
2211                const checkboxes2 = document.querySelectorAll('input[type="checkbox"]');
2212                if (checkboxes2.length > 0) {
2213                    selectAllCheckbox2 = checkboxes2[0];
2214                }
2215            }
2216            
2217            if (!selectAllCheckbox2) {
2218                console.error('Checkbox для отфильтрованных кластеров не найден');
2219                return;
2220            }
2221
2222            selectAllCheckbox2.click();
2223            console.log('Клик на checkbox отфильтрованных кластеров выполнен');
2224            await wait(1000);
2225            
2226            // Открываем меню "Действия"
2227            showStatus('Открытие меню действий...');
2228            console.log('Ищем кнопку "Действия"...');
2229            const actionsButton = document.querySelector('.css-1rll63h');
2230            if (!actionsButton) {
2231                console.error('Кнопка "Действия" не найдена');
2232                showStatus('⚠️ Кнопка "Действия" не найдена', true);
2233                return;
2234            }
2235
2236            console.log('Кнопка "Действия" найдена, кликаем...');
2237            actionsButton.click();
2238            console.log('Клик на "Действия" выполнен');
2239            await wait(300);
2240            
2241            // Кликаем на "Управление"
2242            showStatus('Открытие управления...');
2243            console.log('Ищем кнопку "Управление"...');
2244            const managementButtons = document.querySelectorAll('.css-hq58ok');
2245            console.log(`Найдено кнопок управления: ${managementButtons.length}`);
2246            if (managementButtons.length < 2) {
2247                console.error('Кнопка "Управление" не найдена');
2248                showStatus('⚠️ Кнопка "Управление" не найдена', true);
2249                return;
2250            }
2251
2252            console.log('Кликаем на вторую кнопку "Управление"...');
2253            managementButtons[1].click();
2254            console.log('Клик на "Управление" выполнен');
2255            await wait(300);
2256            
2257            // Кликаем на "Стратегия"
2258            showStatus('Открытие стратегии кластеров...');
2259            console.log('Ищем вкладку "Стратегия"...');
2260            const strategyTabs = document.querySelectorAll('.css-582wun');
2261            console.log(`Найдено вкладок стратегии: ${strategyTabs.length}`);
2262            if (strategyTabs.length < 3) {
2263                console.error('Вкладка "Стратегия" не найдена');
2264                showStatus('⚠️ Вкладка "Стратегия" не найдена', true);
2265                return;
2266            }
2267
2268            console.log('Кликаем на третью вкладку "Стратегия"...');
2269            strategyTabs[2].click();
2270            console.log('Клик на "Стратегия" выполнен');
2271            await wait(300);
2272            
2273            // Вставляем ОБЫЧНУЮ стратегию для всех кластеров
2274            showStatus('Вставка обычной стратегии для всех кластеров...');
2275            const clusterInsertButtons = document.querySelectorAll('.css-5kbhos');
2276            let clusterInsertButton = null;
2277            
2278            for (const btn of clusterInsertButtons) {
2279                if (btn.textContent.includes('Вставить стратегию')) {
2280                    clusterInsertButton = btn;
2281                    break;
2282                }
2283            }
2284            
2285            if (!clusterInsertButton && clusterInsertButtons.length > 0) {
2286                clusterInsertButton = clusterInsertButtons[0];
2287            }
2288            
2289            if (!clusterInsertButton) {
2290                console.error('Кнопка "Вставить стратегию" для кластеров не найдена');
2291                showStatus('⚠️ Кнопка вставки стратегии не найдена', true);
2292                return;
2293            }
2294
2295            // Получаем ОБЫЧНУЮ кластерную стратегию
2296            const currentClusterStrategyCode = await getCurrentClusterStrategy();
2297            console.log('Используем обычную кластерную стратегию, длина:', currentClusterStrategyCode.length);
2298            
2299            // Копируем стратегию в буфер обмена
2300            try {
2301                await navigator.clipboard.writeText(currentClusterStrategyCode);
2302                console.log('✓ Обычная кластерная стратегия скопирована');
2303            } catch {
2304                await GM.setClipboard(currentClusterStrategyCode);
2305                console.log('✓ Обычная кластерная стратегия скопирована через GM');
2306            }
2307            
2308            await wait(500);
2309            
2310            clusterInsertButton.click();
2311            console.log('Клик на "Вставить стратегию" для всех кластеров выполнен');
2312            await wait(1000);
2313            
2314            // Находим поле для ввода ставки
2315            const clusterInputLabels = Array.from(document.querySelectorAll('.MuiInputLabel-root'));
2316            let clusterTargetInput = null;
2317            
2318            for (const label of clusterInputLabels) {
2319                const labelText = label.textContent.trim();
2320                if (labelText.includes('Желаемое значение За корзину')) {
2321                    const inputId = label.getAttribute('for');
2322                    if (inputId) {
2323                        clusterTargetInput = document.getElementById(inputId);
2324                        console.log(`Найдено поле для кластеров: ${labelText}`);
2325                        break;
2326                    }
2327                }
2328            }
2329
2330            if (!clusterTargetInput) {
2331                const clusterInputs = document.querySelectorAll('input[type="number"]');
2332                for (const input of clusterInputs) {
2333                    const name = input.getAttribute('name') || '';
2334                    if (name.includes('CostPerAddedToCart') || name.includes('value')) {
2335                        clusterTargetInput = input;
2336                        console.log(`Найдено поле по имени: ${name}`);
2337                        break;
2338                    }
2339                }
2340            }
2341            
2342            if (clusterTargetInput) {
2343                clusterTargetInput.focus();
2344                clusterTargetInput.value = cartCostRounded.toString();
2345                clusterTargetInput.dispatchEvent(new Event('input', { bubbles: true }));
2346                clusterTargetInput.dispatchEvent(new Event('change', { bubbles: true }));
2347                console.log(`Значение ${cartCostRounded} установлено для всех кластеров`);
2348                await wait(500);
2349            }
2350            
2351            // Нажимаем "Применить"
2352            showStatus('Применение обычной стратегии ко всем кластерам...');
2353            const clusterStrategyApplyButtons = document.querySelectorAll('.css-eqlbov');
2354            if (clusterStrategyApplyButtons.length < 2) {
2355                console.error('Кнопка "Применить" не найдена');
2356                showStatus('⚠️ Кнопка "Применить" не найдена', true);
2357                return;
2358            }
2359
2360            clusterStrategyApplyButtons[1].click();
2361            console.log('Клик на "Применить" обычную стратегию выполнен');
2362            await wait(1000);
2363            
2364            // Закрываем модальное окно
2365            const closeModalButtons = document.querySelectorAll('button[aria-label="Close"]');
2366            if (closeModalButtons.length > 0) {
2367                closeModalButtons[closeModalButtons.length - 1].click();
2368                console.log('Модальное окно закрыто');
2369                await wait(1000);
2370            }
2371            
2372            // Снимаем выделение со всех кластеров
2373            console.log('Снимаем выделение со всех кластеров');
2374            let deselectAllCheckbox = document.querySelector('.css-1ytbthu .css-vlug8u');
2375            if (!deselectAllCheckbox) {
2376                deselectAllCheckbox = document.querySelector('thead .css-vlug8u');
2377            }
2378            if (!deselectAllCheckbox) {
2379                const checkboxes = document.querySelectorAll('input[type="checkbox"]');
2380                if (checkboxes.length > 0) {
2381                    deselectAllCheckbox = checkboxes[0];
2382                }
2383            }
2384            
2385            if (deselectAllCheckbox) {
2386                deselectAllCheckbox.click();
2387                console.log('Клик на checkbox для снятия выделения выполнен');
2388                await wait(1000);
2389            }
2390            
2391            // ТЕПЕРЬ, если включен чекбокс "Удержание места", применяем фильтры
2392            if (shouldApplyHoldPosition) {
2393                console.log('Шаг 2: Применяем фильтры и стратегию удержания места');
2394                await applyHoldPositionToFilteredClusters(cartCostRounded);
2395            }
2396            
2397            // Работаем с автофильтрами
2398            await applyAutofilters();
2399
2400            showStatus(`✅ Полностью готово! Стоимость корзины: ${cartCostRounded}`);
2401
2402            // Проверяем, идет ли массовая обработка
2403            const savedDRR = await GM.getValue('bulkProcessingDRR', null);
2404            if (savedDRR !== null) {
2405                console.log('Массовая обработка: переход к следующей кампании');
2406                await wait(2000);
2407                
2408                const campaignsJson = await GM.getValue('bulkCampaigns', null);
2409                const currentIndex = await GM.getValue('bulkCurrentIndex', 0);
2410                const totalCampaigns = await GM.getValue('bulkTotalCampaigns', 0);
2411                
2412                if (campaignsJson) {
2413                    const campaigns = JSON.parse(campaignsJson);
2414                    const nextIndex = currentIndex + 1;
2415                    
2416                    console.log(`Обработано кампаний: ${nextIndex} из ${totalCampaigns}`);
2417                    
2418                    if (nextIndex < campaigns.length) {
2419                        await GM.setValue('bulkCurrentIndex', nextIndex);
2420                        console.log(`Переходим к кампании ${nextIndex + 1}: ${campaigns[nextIndex]}`);
2421                        // Просто перенаправляем текущую вкладку на следующую кампанию
2422                        window.location.href = campaigns[nextIndex];
2423                    } else {
2424                        console.log('Все кампании обработаны');
2425                        await GM.deleteValue('bulkProcessingDRR');
2426                        await GM.deleteValue('bulkCampaigns');
2427                        await GM.deleteValue('bulkCurrentIndex');
2428                        await GM.deleteValue('bulkTotalCampaigns');
2429                        
2430                        showStatus('✅ Все кампании обработаны!');
2431                        alert('✅ Все кампании обработаны!');
2432                    }
2433                }
2434            }
2435
2436        } catch (error) {
2437            console.error('Ошибка при выполнении стратегии:', error);
2438            showStatus(`Ошибка: ${error.message}`, true);
2439            await handleStrategyError();
2440        }
2441    }
2442
2443    // Функция для применения стратегии удержания места к отфильтрованным кластерам
2444    async function applyHoldPositionToFilteredClusters(cartCostRounded) {
2445        showStatus('Настройка фильтра "Удержание места"...');
2446        await wait(1500);
2447        
2448        // Выбираем дату "За 7 дней"
2449        showStatus('Выбор даты "За 7 дней"...');
2450        const jt7z00Elements = document.querySelectorAll('.css-jt7z00');
2451        
2452        if (jt7z00Elements.length >= 6) {
2453            const clusterIntervalInput = jt7z00Elements[5];
2454            Object.defineProperty(clusterIntervalInput, 'readOnly', { value: false, writable: true });
2455            clusterIntervalInput.focus();
2456            clusterIntervalInput.dispatchEvent(new Event('focusin', { bubbles: true }));
2457            clusterIntervalInput.click();
2458            
2459            await wait(2000);
2460            
2461            const dateButtons = document.querySelectorAll('.css-ghy8jd');
2462            if (dateButtons.length >= 2) {
2463                dateButtons[1].click();
2464                console.log('Клик на "За 7 дней" выполнен');
2465                await wait(1000);
2466                
2467                const applyDateButtons = document.querySelectorAll('.css-7wa720');
2468                if (applyDateButtons.length > 0) {
2469                    applyDateButtons[0].click();
2470                    console.log('Клик на "Применить" дату выполнен');
2471                    await wait(1500);
2472                }
2473            }
2474        }
2475        
2476        // Открываем фильтры
2477        const filtersButton = document.querySelector('.css-a54mx2');
2478        if (!filtersButton) {
2479            console.error('Кнопка "Фильтры" не найдена');
2480            return;
2481        }
2482
2483        filtersButton.click();
2484        console.log('Клик на "Фильтры" выполнен');
2485        await wait(1500);
2486        
2487        // Добавляем фильтр
2488        const addFilterButtons = document.querySelectorAll('.css-8h18y2');
2489        if (addFilterButtons.length < 2) {
2490            console.error('Кнопка "Добавить фильтр" не найдена');
2491            return;
2492        }
2493
2494        addFilterButtons[1].click();
2495        console.log('Клик на "Добавить фильтр" выполнен');
2496        await wait(1500);
2497        
2498        // Выбираем "Среднее место в выдаче"
2499        const filterOptions = document.querySelectorAll('.css-1ytbthu');
2500        if (filterOptions.length < 6) {
2501            console.error('Опция "Среднее место в выдаче" не найдена');
2502            return;
2503        }
2504
2505        filterOptions[5].click();
2506        console.log('Клик на "Среднее место в выдаче" выполнен');
2507        await wait(1500);
2508        
2509        // Очищаем фильтр
2510        const allInputsWithVse = document.querySelectorAll('input[value="Все"]');
2511        let avgPositionInput = allInputsWithVse.length >= 2 ? allInputsWithVse[1] : allInputsWithVse[0];
2512        
2513        if (!avgPositionInput) {
2514            console.error('Input "Среднее место в выдаче" не найден');
2515            return;
2516        }
2517
2518        const inputContainer = avgPositionInput.closest('.MuiInputBase-root');
2519        const clearButton = inputContainer?.querySelector('button');
2520        
2521        if (!clearButton) {
2522            console.error('Кнопка очистки не найдена');
2523            return;
2524        }
2525
2526        clearButton.click();
2527        console.log('Клик на кнопку очистки выполнен');
2528        await wait(1500);
2529        
2530        // Выбираем "Между"
2531        const hiddenInputsForComparison = document.querySelectorAll('input.MuiSelect-nativeInput');
2532        let comparisonContainer = null;
2533        
2534        for (const inp of hiddenInputsForComparison) {
2535            const container = inp.closest('.MuiFormControl-root');
2536            const label = container?.querySelector('label');
2537            if (label && label.textContent.includes('Сравнение')) {
2538                comparisonContainer = container;
2539                break;
2540            }
2541        }
2542        
2543        if (!comparisonContainer) {
2544            console.error('Контейнер "Сравнение" не найден');
2545            return;
2546        }
2547
2548        const arrowButton = comparisonContainer.querySelector('button');
2549        if (!arrowButton) {
2550            console.error('Кнопка со стрелкой не найдена');
2551            return;
2552        }
2553
2554        arrowButton.click();
2555        console.log('Клик на кнопку со стрелкой выполнен');
2556        await wait(1000);
2557        
2558        // Выбираем "Между"
2559        const options = document.querySelectorAll('[role="option"]');
2560        const betweenOption = Array.from(options).find(opt => opt.textContent.trim() === 'Между');
2561        
2562        if (!betweenOption) {
2563            console.error('Опция "Между" не найдена');
2564            return;
2565        }
2566
2567        betweenOption.click();
2568        console.log('Клик на "Между" выполнен');
2569        await wait(1500);
2570        
2571        // Устанавливаем значения "от" и "до"
2572        const allLabels = document.querySelectorAll('label');
2573        let fromInput = null;
2574        let toInput = null;
2575        
2576        for (const label of allLabels) {
2577            const text = label.textContent.trim();
2578            if (text === 'Значение от') {
2579                const inputId = label.getAttribute('for');
2580                if (inputId) {
2581                    fromInput = document.getElementById(inputId);
2582                }
2583            } else if (text === 'Значение до') {
2584                const inputId = label.getAttribute('for');
2585                if (inputId) {
2586                    toInput = document.getElementById(inputId);
2587                }
2588            }
2589        }
2590        
2591        if (!fromInput || !toInput) {
2592            console.error('Поля "от" и "до" не найдены');
2593            return;
2594        }
2595
2596        // Устанавливаем "от" = 1
2597        fromInput.focus();
2598        fromInput.value = '1';
2599        fromInput.dispatchEvent(new Event('input', { bubbles: true }));
2600        fromInput.dispatchEvent(new Event('change', { bubbles: true }));
2601        console.log('Установлено значение "от" = 1');
2602        await wait(500);
2603        
2604        // Устанавливаем "до" = 4
2605        toInput.focus();
2606        toInput.value = '4';
2607        toInput.dispatchEvent(new Event('input', { bubbles: true }));
2608        toInput.dispatchEvent(new Event('change', { bubbles: true }));
2609        console.log('Установлено значение "до" = 4');
2610        await wait(1000);
2611        
2612        // Выделяем отфильтрованные кластеры
2613        showStatus('Выделение отфильтрованных кластеров...');
2614        
2615        // Сначала кликаем на первый чекбокс в списке кластеров
2616        const firstClusterCheckbox = document.querySelector('tbody input[type="checkbox"]');
2617        if (firstClusterCheckbox) {
2618            firstClusterCheckbox.click();
2619            console.log('Клик на первый чекбокс кластера выполнен');
2620            await wait(500);
2621        }
2622        
2623        // Теперь кликаем на общий чекбокс для выделения всех
2624        let selectAllCheckbox2 = document.querySelector('.css-1ytbthu .css-vlug8u');
2625        if (!selectAllCheckbox2) {
2626            selectAllCheckbox2 = document.querySelector('thead .css-vlug8u');
2627        }
2628        if (!selectAllCheckbox2) {
2629            const checkboxes2 = document.querySelectorAll('input[type="checkbox"]');
2630            if (checkboxes2.length > 0) {
2631                selectAllCheckbox2 = checkboxes2[0];
2632            }
2633        }
2634        
2635        if (!selectAllCheckbox2) {
2636            console.error('Checkbox для отфильтрованных кластеров не найден');
2637            return;
2638        }
2639
2640        selectAllCheckbox2.click();
2641        console.log('Клик на checkbox отфильтрованных кластеров выполнен');
2642        await wait(1000);
2643        
2644        // Открываем меню "Действия"
2645        showStatus('Открытие меню действий для отфильтрованных кластеров...');
2646        const actionsButton2 = document.querySelector('.css-1rll63h');
2647        if (!actionsButton2) {
2648            console.error('Кнопка "Действия" не найдена');
2649            return;
2650        }
2651
2652        actionsButton2.click();
2653        await wait(300);
2654        
2655        // Кликаем на "Управление"
2656        const managementButtons2 = document.querySelectorAll('.css-hq58ok');
2657        if (managementButtons2.length < 2) {
2658            console.error('Кнопка "Управление" не найдена');
2659            return;
2660        }
2661
2662        managementButtons2[1].click();
2663        await wait(300);
2664        
2665        // Кликаем на "Стратегия"
2666        const strategyTabs2 = document.querySelectorAll('.css-582wun');
2667        if (strategyTabs2.length < 3) {
2668            console.error('Вкладка "Стратегия" не найдена');
2669            return;
2670        }
2671
2672        strategyTabs2[2].click();
2673        await wait(300);
2674        
2675        // Вставляем стратегию УДЕРЖАНИЯ МЕСТА
2676        showStatus('Вставка стратегии удержания места...');
2677        const clusterInsertButtons2 = document.querySelectorAll('.css-5kbhos');
2678        let clusterInsertButton2 = null;
2679        
2680        for (const btn of clusterInsertButtons2) {
2681            if (btn.textContent.includes('Вставить стратегию')) {
2682                clusterInsertButton2 = btn;
2683                break;
2684            }
2685        }
2686        
2687        if (!clusterInsertButton2 && clusterInsertButtons2.length > 0) {
2688            clusterInsertButton2 = clusterInsertButtons2[0];
2689        }
2690        
2691        if (!clusterInsertButton2) {
2692            console.error('Кнопка "Вставить стратегию" для отфильтрованных кластеров не найдена');
2693            return;
2694        }
2695
2696        // Получаем стратегию УДЕРЖАНИЯ МЕСТА
2697        const holdPositionClusterStrategyCode = await getHoldPositionClusterStrategy();
2698        console.log('Используем стратегию удержания места, длина:', holdPositionClusterStrategyCode.length);
2699        
2700        try {
2701            await navigator.clipboard.writeText(holdPositionClusterStrategyCode);
2702            console.log('✓ Стратегия удержания места скопирована');
2703        } catch {
2704            await GM.setClipboard(holdPositionClusterStrategyCode);
2705            console.log('✓ Стратегия удержания места скопирована через GM');
2706        }
2707        
2708        await wait(500);
2709        
2710        clusterInsertButton2.click();
2711        console.log('Клик на "Вставить стратегию" удержания места выполнен');
2712        await wait(1000);
2713        
2714        // Находим поле для ввода ставки
2715        const clusterInputLabels2 = Array.from(document.querySelectorAll('.MuiInputLabel-root'));
2716        let clusterTargetInput2 = null;
2717        
2718        for (const label of clusterInputLabels2) {
2719            const labelText = label.textContent.trim();
2720            if (labelText.includes('Желаемое значение За корзину')) {
2721                const inputId = label.getAttribute('for');
2722                if (inputId) {
2723                    clusterTargetInput2 = document.getElementById(inputId);
2724                    break;
2725                }
2726            }
2727        }
2728
2729        if (!clusterTargetInput2) {
2730            const clusterInputs2 = document.querySelectorAll('input[type="number"]');
2731            for (const input of clusterInputs2) {
2732                const name = input.getAttribute('name') || '';
2733                if (name.includes('CostPerAddedToCart') || name.includes('value')) {
2734                    clusterTargetInput2 = input;
2735                    break;
2736                }
2737            }
2738        }
2739        
2740        if (clusterTargetInput2) {
2741            clusterTargetInput2.focus();
2742            clusterTargetInput2.value = cartCostRounded.toString();
2743            clusterTargetInput2.dispatchEvent(new Event('input', { bubbles: true }));
2744            clusterTargetInput2.dispatchEvent(new Event('change', { bubbles: true }));
2745            console.log(`Значение ${cartCostRounded} установлено для отфильтрованных кластеров`);
2746            await wait(500);
2747        }
2748        
2749        // Нажимаем "Применить"
2750        showStatus('Применение стратегии удержания места...');
2751        const clusterStrategyApplyButtons2 = document.querySelectorAll('.css-eqlbov');
2752        if (clusterStrategyApplyButtons2.length >= 2) {
2753            clusterStrategyApplyButtons2[1].click();
2754            console.log('Клик на "Применить" стратегию удержания места выполнен');
2755            await wait(1000);
2756            
2757            // Закрываем модальное окно
2758            const closeModalButtons2 = document.querySelectorAll('button[aria-label="Close"]');
2759            if (closeModalButtons2.length > 0) {
2760                closeModalButtons2[closeModalButtons2.length - 1].click();
2761                console.log('Модальное окно закрыто');
2762                await wait(1000);
2763            }
2764        }
2765    }
2766
2767    // Функция для применения автофильтров
2768    async function applyAutofilters() {
2769        showStatus('Открытие автофильтров...');
2770        
2771        const autofilterAccordion = document.getElementById('bidder-constructor');
2772        if (!autofilterAccordion) {
2773            console.error('Аккордеон "Автофильтры" не найден');
2774            return;
2775        }
2776
2777        const accordionButton = autofilterAccordion.querySelector('button[aria-expanded]');
2778        const isExpanded = accordionButton && accordionButton.getAttribute('aria-expanded') === 'true';
2779        
2780        if (!isExpanded && accordionButton) {
2781            accordionButton.click();
2782            console.log('Аккордеон "Автофильтры" раскрыт');
2783            await wait(1000);
2784        }
2785        
2786        // Кликаем на "Шаблоны"
2787        showStatus('Открытие шаблонов...');
2788        const templatesButtons = autofilterAccordion.querySelectorAll('button');
2789        let templateButton = null;
2790        
2791        for (const btn of templatesButtons) {
2792            if (btn.textContent.trim() === 'Шаблоны') {
2793                templateButton = btn;
2794                break;
2795            }
2796        }
2797        
2798        if (!templateButton) {
2799            console.error('Кнопка "Шаблоны" не найдена');
2800            return;
2801        }
2802
2803        templateButton.click();
2804        console.log('Кнопка "Шаблоны" выбрана');
2805        await wait(500);
2806        
2807        // Выбираем "Расширение"
2808        showStatus('Выбор шаблона "Расширение"...');
2809        const allElements = document.querySelectorAll('div, button, span, p');
2810        let extensionTemplate = null;
2811        
2812        for (const el of allElements) {
2813            const text = el.textContent.trim();
2814            if (text === 'Расширение') {
2815                extensionTemplate = el;
2816                break;
2817            }
2818        }
2819        
2820        if (!extensionTemplate) {
2821            console.error('Шаблон "Расширение" не найден');
2822            return;
2823        }
2824
2825        extensionTemplate.click();
2826        console.log('Шаблон "Расширение" выбран');
2827        await wait(500);
2828        
2829        // Сохраняем
2830        showStatus('Сохранение автофильтров...');
2831        const saveButtonsAfterTemplate = document.querySelectorAll('button');
2832        let saveAutofilterButton = null;
2833        
2834        for (const btn of saveButtonsAfterTemplate) {
2835            if (btn.textContent.trim() === 'Сохранить') {
2836                saveAutofilterButton = btn;
2837                break;
2838            }
2839        }
2840        
2841        if (!saveAutofilterButton) {
2842            console.error('Кнопка "Сохранить" не найдена');
2843            return;
2844        }
2845
2846        saveAutofilterButton.click();
2847        console.log('Клик на "Сохранить" автофильтры выполнен');
2848        await wait(1000);
2849        
2850        // Применяем автофильтры вручную
2851        showStatus('Применение автофильтров вручную...');
2852        const applyButtonsAfterSave = document.querySelectorAll('button');
2853        let applyAutofilterButton = null;
2854        
2855        for (const btn of applyButtonsAfterSave) {
2856            if (btn.textContent.trim() === 'Применить автофильтры вручную') {
2857                applyAutofilterButton = btn;
2858                break;
2859            }
2860        }
2861        
2862        if (!applyAutofilterButton) {
2863            console.error('Кнопка "Применить автофильтры вручную" не найдена');
2864            return;
2865        }
2866
2867        applyAutofilterButton.click();
2868        console.log('Клик на "Применить автофильтры вручную" выполнен');
2869        await wait(1000);
2870    }
2871
2872    // Функция для обработки ошибок и перехода к следующей кампании
2873    async function handleStrategyError() {
2874        const savedDRR = await GM.getValue('bulkProcessingDRR', null);
2875        if (savedDRR !== null) {
2876            console.log('Обнаружена ошибка при массовой обработке, ждем 10 секунд');
2877            showStatus('⚠️ Ошибка! Переход к следующей кампании через 10 секунд...', true);
2878            
2879            for (let i = 10; i > 0; i--) {
2880                showStatus(`⚠️ Ошибка! Переход к следующей через ${i} сек...`, true);
2881                await wait(1000);
2882            }
2883            
2884            const campaignsJson = await GM.getValue('bulkCampaigns', null);
2885            const currentIndex = await GM.getValue('bulkCurrentIndex', 0);
2886            const totalCampaigns = await GM.getValue('bulkTotalCampaigns', 0);
2887            
2888            if (campaignsJson) {
2889                const campaigns = JSON.parse(campaignsJson);
2890                const nextIndex = currentIndex + 1;
2891                
2892                console.log(`Обработано кампаний: ${nextIndex} из ${totalCampaigns}`);
2893                
2894                if (nextIndex < campaigns.length) {
2895                    await GM.setValue('bulkCurrentIndex', nextIndex);
2896                    console.log(`Переходим к кампании ${nextIndex + 1}: ${campaigns[nextIndex]}`);
2897                    // Просто перенаправляем текущую вкладку на следующую кампанию
2898                    window.location.href = campaigns[nextIndex];
2899                } else {
2900                    console.log('Все кампании обработаны');
2901                    await GM.deleteValue('bulkProcessingDRR');
2902                    await GM.deleteValue('bulkCampaigns');
2903                    await GM.deleteValue('bulkCurrentIndex');
2904                    await GM.deleteValue('bulkTotalCampaigns');
2905                    
2906                    showStatus('✅ Все кампании обработаны!');
2907                    alert('✅ Все кампании обработаны!');
2908                }
2909            }
2910        }
2911    }
2912
2913    // Инициализация
2914    function init() {
2915        console.log('Инициализация расширения');
2916        
2917        if (window.location.href.includes('/advert/campaigns')) {
2918            console.log('Страница списка кампаний обнаружена');
2919            setTimeout(() => {
2920                if (document.body) {
2921                    createBulkUI();
2922                } else {
2923                    console.error('Body не найден');
2924                }
2925            }, 1000);
2926        } else if (window.location.href.includes('/campaigns/auto-campaigns/') && window.location.href.includes('/campaign')) {
2927            console.log('Страница кампании обнаружена');
2928            setTimeout(() => {
2929                if (document.body) {
2930                    createUI();
2931                } else {
2932                    console.error('Body не найден');
2933                }
2934            }, 1000);
2935        } else {
2936            console.log('Не на странице кампании, UI не создается');
2937        }
2938    }
2939
2940    // Запускаем инициализацию
2941    init();
2942
2943})();