MP Manager Cluster Auto Strategy Setter

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

Size

142.2 KB

Version

1.8.133

Created

Mar 11, 2026

Updated

about 1 month ago

1// ==UserScript==
2// @name		MP Manager Cluster Auto Strategy Setter
3// @description		Автоматическая установка стратегии рекламной кампании на основе статистики
4// @version		1.8.133
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 = 'eyJjYW1wYWlnblR5cGUiOiJTZWFyY2hDYXRhbG9nIiwidmVyc2lvbiI6MiwiZGF0YSI6eyJzdGF0ZSI6IkVuYWJsZWQiLCJtb2RlIjp7InR5cGUiOiJQb3NpdGlvbiIsInBhdXNlVHlwZSI6IlJlc3VtZSJ9LCJzdHJhdGVneSI6eyJ0eXBlIjoiQ2FtcGFpZ25TdGF0cyIsIm1vZGUiOiJQbGFjZSIsImJpZE1vZGUiOiJDb3N0UGVyQ2xpY2siLCJjbHVzdGVyU3RhdHMiOnsibWF4QmlkIjo4MDAwLCJtaW5CaWQiOjQwMCwiaW50ZXJ2YWwiOiJUaHJlZURheXMiLCJydWxlcyI6W3sidHlwZSI6IkF2ZXJhZ2VQb3NpdGlvbiIsIm1vZGUiOiJWYWx1ZSIsInZhbHVlIjoyfSx7InR5cGUiOiJDb3N0UGVyQWRkZWRUb0NhcnQiLCJtb2RlIjoiQXZlcmFnZVZhbHVlIn1dfSwicGxhY2VTdHJhdGVneSI6eyJ0eXBlIjoiS2V5d29yZHMiLCJrZXl3b3JkcyI6eyJrZXl3b3JkcyI6W119fSwiaXNDbHVzdGVyIjpmYWxzZX19';
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            // Собираем все кнопки "Вставить стратегию"
1990            const mainInsertStrategyButtons = [];
1991            for (const btn of insertButtons) {
1992                if (btn.textContent.includes('Вставить стратегию')) {
1993                    mainInsertStrategyButtons.push(btn);
1994                }
1995            }
1996            
1997            // Берем первую кнопку для основной стратегии
1998            if (mainInsertStrategyButtons.length >= 1) {
1999                insertButton = mainInsertStrategyButtons[0];
2000                console.log('Используем первую кнопку "Вставить стратегию" для основной стратегии');
2001            }
2002            
2003            if (!insertButton) {
2004                console.error('Кнопка "Вставить стратегию" не найдена');
2005                showStatus('⚠️ Кнопка вставки стратегии не найдена', true);
2006                await handleStrategyError();
2007                return;
2008            }
2009
2010            // Получаем текущую выбранную стратегию
2011            let currentStrategyCode;
2012            if (shouldApplyHoldPosition) {
2013                currentStrategyCode = await getHoldPositionStrategy();
2014                console.log('Используем стратегию удержания места, длина:', currentStrategyCode.length);
2015            } else {
2016                currentStrategyCode = await getCurrentStrategy();
2017                console.log('Используем обычную стратегию, длина:', currentStrategyCode.length);
2018            }
2019            
2020            // Копируем код стратегии в буфер обмена
2021            console.log('Копируем стратегию в буфер обмена...');
2022            
2023            try {
2024                await navigator.clipboard.writeText(currentStrategyCode);
2025                console.log('✓ Стратегия скопирована через navigator.clipboard');
2026            } catch {
2027                console.log('navigator.clipboard не сработал, пробуем GM.setClipboard...');
2028                try {
2029                    await GM.setClipboard(currentStrategyCode);
2030                    console.log('✓ Стратегия скопирована через GM.setClipboard');
2031                } catch (e2) {
2032                    console.error('Ошибка копирования через GM.setClipboard:', e2.message);
2033                }
2034            }
2035            
2036            await wait(500);
2037
2038            insertButton.click();
2039            console.log('Клик на "Вставить стратегию" выполнен');
2040            await wait(500);
2041            
2042            console.log('✓ Стратегия вставлена из буфера обмена');
2043            await wait(500);
2044
2045            // Шаг 5: Находим поле "Желаемое значение" и вставляем результат
2046            showStatus('Заполнение поля...');
2047            
2048            const inputLabels = Array.from(document.querySelectorAll('.MuiInputLabel-root'));
2049            let targetInput = null;
2050
2051            for (const label of inputLabels) {
2052                const labelText = label.textContent;
2053                if (labelText.includes('Желаемое значение За корзину')) {
2054                    const inputId = label.getAttribute('for');
2055                    if (inputId) {
2056                        targetInput = document.getElementById(inputId);
2057                        console.log(`Найдено поле: ${labelText}, id: ${inputId}`);
2058                        break;
2059                    }
2060                }
2061            }
2062
2063            if (!targetInput) {
2064                const inputs = document.querySelectorAll('input[type="number"]');
2065                for (const input of inputs) {
2066                    const name = input.getAttribute('name') || '';
2067                    if (name.includes('rules') && name.includes('value')) {
2068                        targetInput = input;
2069                        break;
2070                    }
2071                }
2072            }
2073
2074            if (!targetInput) {
2075                showStatus('Ошибка: поле для ввода не найдено', true);
2076                console.error('Не удалось найти поле для ввода значения');
2077                await handleStrategyError();
2078                return;
2079            }
2080
2081            targetInput.focus();
2082            targetInput.value = cartCostRounded.toString();
2083            
2084            const inputEvent = new Event('input', { bubbles: true });
2085            const changeEvent = new Event('change', { bubbles: true });
2086            targetInput.dispatchEvent(inputEvent);
2087            targetInput.dispatchEvent(changeEvent);
2088            
2089            console.log(`Значение ${cartCostRounded} установлено в поле ${targetInput.id}`);
2090            await wait(500);
2091
2092            // Шаг 6: Нажимаем "Сохранить"
2093            showStatus('Сохранение...');
2094            const saveButtons = document.querySelectorAll('button');
2095            let saveButton = null;
2096
2097            for (const btn of saveButtons) {
2098                if (btn.textContent.trim() === 'Сохранить') {
2099                    saveButton = btn;
2100                    break;
2101                }
2102            }
2103
2104            if (!saveButton) {
2105                showStatus('Ошибка: кнопка "Сохранить" не найдена', true);
2106                await handleStrategyError();
2107                return;
2108            }
2109
2110            saveButton.click();
2111            console.log('Клик на "Сохранить" выполнен');
2112            await wait(500);
2113
2114            showStatus(`✅ Готово! Стоимость корзины: ${cartCostRounded}`);
2115            console.log('Стратегия успешно установлена');
2116
2117            // Шаг 7: Работа с кластерами
2118            // Проверяем чекбоксы из обеих панелей
2119            const applyToClusters = document.getElementById('apply-to-clusters');
2120            const bulkApplyToClusters = document.getElementById('bulk-apply-to-clusters');
2121            const shouldApplyToClusters = applyToClusters ? applyToClusters.checked : 
2122                (bulkApplyToClusters ? bulkApplyToClusters.checked : true);
2123            
2124            if (!shouldApplyToClusters) {
2125                console.log('Применение стратегии к кластерам отключено');
2126                showStatus('✅ Готово! Кластеры пропущены');
2127                
2128                // Проверяем, идет ли массовая обработка
2129                const savedDRR = await GM.getValue('bulkProcessingDRR', null);
2130                if (savedDRR !== null) {
2131                    console.log('Массовая обработка: переход к следующей кампании');
2132                    await wait(2000);
2133                    
2134                    const campaignsJson = await GM.getValue('bulkCampaigns', null);
2135                    const currentIndex = await GM.getValue('bulkCurrentIndex', 0);
2136                    const totalCampaigns = await GM.getValue('bulkTotalCampaigns', 0);
2137                    
2138                    if (campaignsJson) {
2139                        const campaigns = JSON.parse(campaignsJson);
2140                        const nextIndex = currentIndex + 1;
2141                        
2142                        console.log(`Обработано кампаний: ${nextIndex} из ${totalCampaigns}`);
2143                        
2144                        if (nextIndex < campaigns.length) {
2145                            await GM.setValue('bulkCurrentIndex', nextIndex);
2146                            console.log(`Переходим к кампании ${nextIndex + 1}: ${campaigns[nextIndex]}`);
2147                            // Просто перенаправляем текущую вкладку на следующую кампанию
2148                            window.location.href = campaigns[nextIndex];
2149                        } else {
2150                            console.log('Все кампании обработаны');
2151                            await GM.deleteValue('bulkProcessingDRR');
2152                            await GM.deleteValue('bulkCampaigns');
2153                            await GM.deleteValue('bulkCurrentIndex');
2154                            await GM.deleteValue('bulkTotalCampaigns');
2155                            
2156                            showStatus('✅ Все кампании обработаны!');
2157                            alert('✅ Все кампании обработаны!');
2158                        }
2159                    }
2160                }
2161                return;
2162            }
2163
2164            console.log('Применение стратегии к кластерам включено');
2165            
2166            // Переходим во вкладку "Кластеры"
2167            const tabs = Array.from(document.querySelectorAll('button[role="tab"]'));
2168            const clustersTab = tabs.find(tab => tab.textContent.trim() === 'Кластеры');
2169            if (!clustersTab) {
2170                console.error('Вкладка "Кластеры" не найдена');
2171                showStatus('⚠️ Вкладка "Кластеры" не найдена', true);
2172                return;
2173            }
2174
2175            clustersTab.click();
2176            console.log('Клик на "Кластеры" выполнен');
2177            await wait(1000);
2178            
2179            // Ждем загрузки кластеров
2180            let loadingAttempts = 0;
2181            while (loadingAttempts < 10) {
2182                const skeleton = document.querySelector('.MuiSkeleton-root');
2183                if (!skeleton) {
2184                    console.log('Кластеры загружены');
2185                    break;
2186                }
2187                console.log(`Ожидание загрузки кластеров, попытка ${loadingAttempts + 1}`);
2188                await wait(500);
2189                loadingAttempts++;
2190            }
2191            
2192            // СНАЧАЛА применяем обычную стратегию ко ВСЕМ кластерам
2193            showStatus('Применение обычной стратегии ко всем кластерам...');
2194            console.log('Шаг 1: Применяем обычную стратегию ко всем кластерам');
2195            
2196            // Выделяем отфильтрованные кластеры
2197            showStatus('Выделение отфильтрованных кластеров...');
2198            
2199            // Сначала кликаем на первый чекбокс в списке кластеров
2200            const firstClusterCheckbox = document.querySelector('tbody input[type="checkbox"]');
2201            if (firstClusterCheckbox) {
2202                firstClusterCheckbox.click();
2203                console.log('Клик на первый чекбокс кластера выполнен');
2204                await wait(500);
2205            }
2206            
2207            // Теперь кликаем на общий чекбокс для выделения всех
2208            let selectAllCheckbox2 = document.querySelector('.css-1ytbthu .css-vlug8u');
2209            if (!selectAllCheckbox2) {
2210                selectAllCheckbox2 = document.querySelector('thead .css-vlug8u');
2211            }
2212            if (!selectAllCheckbox2) {
2213                const checkboxes2 = document.querySelectorAll('input[type="checkbox"]');
2214                if (checkboxes2.length > 0) {
2215                    selectAllCheckbox2 = checkboxes2[0];
2216                }
2217            }
2218            
2219            if (!selectAllCheckbox2) {
2220                console.error('Checkbox для отфильтрованных кластеров не найден');
2221                return;
2222            }
2223
2224            selectAllCheckbox2.click();
2225            console.log('Клик на checkbox отфильтрованных кластеров выполнен');
2226            await wait(1000);
2227            
2228            // Открываем меню "Действия"
2229            showStatus('Открытие меню действий...');
2230            console.log('Ищем кнопку "Действия"...');
2231            const actionsButton = document.querySelector('.css-1rll63h');
2232            if (!actionsButton) {
2233                console.error('Кнопка "Действия" не найдена');
2234                showStatus('⚠️ Кнопка "Действия" не найдена', true);
2235                return;
2236            }
2237
2238            console.log('Кнопка "Действия" найдена, кликаем...');
2239            actionsButton.click();
2240            console.log('Клик на "Действия" выполнен');
2241            await wait(300);
2242            
2243            // Кликаем на "Управление"
2244            showStatus('Открытие управления...');
2245            console.log('Ищем кнопку "Управление"...');
2246            const managementButtons = document.querySelectorAll('.css-hq58ok');
2247            console.log(`Найдено кнопок управления: ${managementButtons.length}`);
2248            if (managementButtons.length < 2) {
2249                console.error('Кнопка "Управление" не найдена');
2250                showStatus('⚠️ Кнопка "Управление" не найдена', true);
2251                return;
2252            }
2253
2254            console.log('Кликаем на вторую кнопку "Управление"...');
2255            managementButtons[1].click();
2256            console.log('Клик на "Управление" выполнен');
2257            await wait(300);
2258            
2259            // Кликаем на "Стратегия"
2260            showStatus('Открытие стратегии кластеров...');
2261            console.log('Ищем вкладку "Стратегия"...');
2262            const strategyTabs = document.querySelectorAll('.css-582wun');
2263            console.log(`Найдено вкладок стратегии: ${strategyTabs.length}`);
2264            if (strategyTabs.length < 3) {
2265                console.error('Вкладка "Стратегия" не найдена');
2266                showStatus('⚠️ Вкладка "Стратегия" не найдена', true);
2267                return;
2268            }
2269
2270            console.log('Кликаем на третью вкладку "Стратегия"...');
2271            strategyTabs[2].click();
2272            console.log('Клик на "Стратегия" выполнен');
2273            await wait(300);
2274            
2275            // Вставляем ОБЫЧНУЮ стратегию для всех кластеров
2276            showStatus('Вставка обычной стратегии для всех кластеров...');
2277            const clusterInsertButtons = document.querySelectorAll('.css-5kbhos');
2278            let clusterInsertButton = null;
2279            
2280            // Собираем все кнопки "Вставить стратегию"
2281            const insertStrategyButtons = [];
2282            for (const btn of clusterInsertButtons) {
2283                if (btn.textContent.includes('Вставить стратегию')) {
2284                    insertStrategyButtons.push(btn);
2285                }
2286            }
2287            
2288            // Берем вторую кнопку (индекс 1)
2289            if (insertStrategyButtons.length >= 2) {
2290                clusterInsertButton = insertStrategyButtons[1];
2291                console.log('Используем вторую кнопку "Вставить стратегию" для кластеров');
2292            } else if (insertStrategyButtons.length === 1) {
2293                clusterInsertButton = insertStrategyButtons[0];
2294                console.log('Найдена только одна кнопка, используем её');
2295            }
2296            
2297            if (!clusterInsertButton) {
2298                console.error('Кнопка "Вставить стратегию" для кластеров не найдена');
2299                showStatus('⚠️ Кнопка вставки стратегии не найдена', true);
2300                return;
2301            }
2302
2303            // Получаем ОБЫЧНУЮ кластерную стратегию
2304            const currentClusterStrategyCode = await getCurrentClusterStrategy();
2305            console.log('Используем обычную кластерную стратегию, длина:', currentClusterStrategyCode.length);
2306            
2307            // Копируем стратегию в буфер обмена
2308            try {
2309                await navigator.clipboard.writeText(currentClusterStrategyCode);
2310                console.log('✓ Обычная кластерная стратегия скопирована');
2311            } catch {
2312                await GM.setClipboard(currentClusterStrategyCode);
2313                console.log('✓ Обычная кластерная стратегия скопирована через GM');
2314            }
2315            
2316            await wait(500);
2317            
2318            clusterInsertButton.click();
2319            console.log('Клик на "Вставить стратегию" для всех кластеров выполнен');
2320            await wait(1000);
2321            
2322            // Находим поле для ввода ставки
2323            const clusterInputLabels = Array.from(document.querySelectorAll('.MuiInputLabel-root'));
2324            let clusterTargetInput = null;
2325            
2326            // Ищем второй input с меткой "Желаемое значение За корзину"
2327            let foundInputs = [];
2328            for (const label of clusterInputLabels) {
2329                const labelText = label.textContent.trim();
2330                if (labelText.includes('Желаемое значение За корзину')) {
2331                    const inputId = label.getAttribute('for');
2332                    if (inputId) {
2333                        const input = document.getElementById(inputId);
2334                        if (input) {
2335                            foundInputs.push(input);
2336                            console.log(`Найдено поле для кластеров: ${labelText}, id: ${inputId}`);
2337                        }
2338                    }
2339                }
2340            }
2341            
2342            // Берем второй найденный input (индекс 1)
2343            if (foundInputs.length >= 2) {
2344                clusterTargetInput = foundInputs[1];
2345                console.log(`Используем второй input для кластеров: ${clusterTargetInput.id}`);
2346            } else if (foundInputs.length === 1) {
2347                clusterTargetInput = foundInputs[0];
2348                console.log(`Найден только один input, используем его: ${clusterTargetInput.id}`);
2349            }
2350
2351            if (clusterTargetInput) {
2352                clusterTargetInput.focus();
2353                clusterTargetInput.value = cartCostRounded.toString();
2354                clusterTargetInput.dispatchEvent(new Event('input', { bubbles: true }));
2355                clusterTargetInput.dispatchEvent(new Event('change', { bubbles: true }));
2356                console.log(`Значение ${cartCostRounded} установлено для всех кластеров в поле ${clusterTargetInput.id}`);
2357                await wait(500);
2358            }
2359            
2360            // Нажимаем "Применить"
2361            showStatus('Применение обычной стратегии ко всем кластерам...');
2362            const clusterStrategyApplyButtons = document.querySelectorAll('.css-eqlbov');
2363            if (clusterStrategyApplyButtons.length >= 2) {
2364                clusterStrategyApplyButtons[1].click();
2365                console.log('Клик на "Применить" обычную стратегию выполнен');
2366                await wait(1000);
2367                
2368                // Закрываем модальное окно
2369                const closeModalButtons = document.querySelectorAll('button[aria-label="Close"]');
2370                if (closeModalButtons.length > 0) {
2371                    closeModalButtons[closeModalButtons.length - 1].click();
2372                    console.log('Модальное окно закрыто');
2373                    await wait(1000); // Ждем после закрытия модального окна, выделение снимется автоматически
2374                }
2375            }
2376            
2377            // ЗАТЕМ, если включен чекбокс "Удержание места", применяем фильтры
2378            if (shouldApplyHoldPosition) {
2379                console.log('Шаг 2: Применяем фильтры и стратегию удержания места');
2380                await applyHoldPositionToFilteredClusters(cartCostRounded);
2381            }
2382            
2383            // Работаем с автофильтрами
2384            await applyAutofilters();
2385
2386            showStatus(`✅ Полностью готово! Стоимость корзины: ${cartCostRounded}`);
2387
2388            // Проверяем, идет ли массовая обработка
2389            const savedDRR = await GM.getValue('bulkProcessingDRR', null);
2390            if (savedDRR !== null) {
2391                console.log('Массовая обработка: переход к следующей кампании');
2392                await wait(2000);
2393                
2394                const campaignsJson = await GM.getValue('bulkCampaigns', null);
2395                const currentIndex = await GM.getValue('bulkCurrentIndex', 0);
2396                const totalCampaigns = await GM.getValue('bulkTotalCampaigns', 0);
2397                
2398                if (campaignsJson) {
2399                    const campaigns = JSON.parse(campaignsJson);
2400                    const nextIndex = currentIndex + 1;
2401                    
2402                    console.log(`Обработано кампаний: ${nextIndex} из ${totalCampaigns}`);
2403                    
2404                    if (nextIndex < campaigns.length) {
2405                        await GM.setValue('bulkCurrentIndex', nextIndex);
2406                        console.log(`Переходим к кампании ${nextIndex + 1}: ${campaigns[nextIndex]}`);
2407                        // Просто перенаправляем текущую вкладку на следующую кампанию
2408                        window.location.href = campaigns[nextIndex];
2409                    } else {
2410                        console.log('Все кампании обработаны');
2411                        await GM.deleteValue('bulkProcessingDRR');
2412                        await GM.deleteValue('bulkCampaigns');
2413                        await GM.deleteValue('bulkCurrentIndex');
2414                        await GM.deleteValue('bulkTotalCampaigns');
2415                        
2416                        showStatus('✅ Все кампании обработаны!');
2417                        alert('✅ Все кампании обработаны!');
2418                    }
2419                }
2420            }
2421
2422        } catch (error) {
2423            console.error('Ошибка при выполнении стратегии:', error);
2424            showStatus(`Ошибка: ${error.message}`, true);
2425            await handleStrategyError();
2426        }
2427    }
2428
2429    // Функция для применения стратегии удержания места к отфильтрованным кластерам
2430    async function applyHoldPositionToFilteredClusters(cartCostRounded) {
2431        showStatus('Настройка фильтра "Удержание места"...');
2432        await wait(1500);
2433        
2434        // Выбираем дату "За 7 дней"
2435        showStatus('Выбор даты "За 7 дней"...');
2436        const jt7z00Elements = document.querySelectorAll('.css-jt7z00');
2437        
2438        if (jt7z00Elements.length >= 6) {
2439            const clusterIntervalInput = jt7z00Elements[5];
2440            Object.defineProperty(clusterIntervalInput, 'readOnly', { value: false, writable: true });
2441            clusterIntervalInput.focus();
2442            clusterIntervalInput.dispatchEvent(new Event('focusin', { bubbles: true }));
2443            clusterIntervalInput.click();
2444            
2445            await wait(2000);
2446            
2447            const dateButtons = document.querySelectorAll('.css-ghy8jd');
2448            if (dateButtons.length >= 2) {
2449                dateButtons[1].click();
2450                console.log('Клик на "За 7 дней" выполнен');
2451                await wait(1000);
2452                
2453                const applyDateButtons = document.querySelectorAll('.css-7wa720');
2454                if (applyDateButtons.length > 0) {
2455                    applyDateButtons[0].click();
2456                    console.log('Клик на "Применить" дату выполнен');
2457                    await wait(1500);
2458                }
2459            }
2460        }
2461        
2462        // Открываем фильтры
2463        const filtersButton = document.querySelector('.css-a54mx2');
2464        if (!filtersButton) {
2465            console.error('Кнопка "Фильтры" не найдена');
2466            return;
2467        }
2468
2469        filtersButton.click();
2470        console.log('Клик на "Фильтры" выполнен');
2471        await wait(1500);
2472        
2473        // Добавляем фильтр
2474        const addFilterButtons = document.querySelectorAll('.css-8h18y2');
2475        if (addFilterButtons.length < 2) {
2476            console.error('Кнопка "Добавить фильтр" не найдена');
2477            return;
2478        }
2479
2480        addFilterButtons[1].click();
2481        console.log('Клик на "Добавить фильтр" выполнен');
2482        await wait(1500);
2483        
2484        // Выбираем "Среднее место в выдаче"
2485        const filterOptions = document.querySelectorAll('.css-1ytbthu');
2486        if (filterOptions.length < 8) {
2487            console.error('Опция "Среднее место в выдаче" не найдена');
2488            return;
2489        }
2490
2491        filterOptions[7].click();
2492        console.log('Клик на "Среднее место в выдаче" выполнен');
2493        await wait(1500);
2494        
2495        // Очищаем фильтр
2496        const allInputsWithVse = document.querySelectorAll('input[value="Все"]');
2497        let avgPositionInput = allInputsWithVse.length >= 2 ? allInputsWithVse[1] : allInputsWithVse[0];
2498        
2499        if (!avgPositionInput) {
2500            console.error('Input "Среднее место в выдаче" не найден');
2501            return;
2502        }
2503
2504        const inputContainer = avgPositionInput.closest('.MuiInputBase-root');
2505        const clearButton = inputContainer?.querySelector('button');
2506        
2507        if (!clearButton) {
2508            console.error('Кнопка очистки не найдена');
2509            return;
2510        }
2511
2512        clearButton.click();
2513        console.log('Клик на кнопку очистки выполнен');
2514        await wait(1500);
2515        
2516        // Выбираем "Между"
2517        const hiddenInputsForComparison = document.querySelectorAll('input.MuiSelect-nativeInput');
2518        let comparisonContainer = null;
2519        
2520        for (const inp of hiddenInputsForComparison) {
2521            const container = inp.closest('.MuiFormControl-root');
2522            const label = container?.querySelector('label');
2523            if (label && label.textContent.includes('Сравнение')) {
2524                comparisonContainer = container;
2525                break;
2526            }
2527        }
2528        
2529        if (!comparisonContainer) {
2530            console.error('Контейнер "Сравнение" не найден');
2531            return;
2532        }
2533
2534        const arrowButton = comparisonContainer.querySelector('button');
2535        if (!arrowButton) {
2536            console.error('Кнопка со стрелкой не найдена');
2537            return;
2538        }
2539
2540        arrowButton.click();
2541        console.log('Клик на кнопку со стрелкой выполнен');
2542        await wait(1000);
2543        
2544        // Выбираем "Между"
2545        const options = document.querySelectorAll('[role="option"]');
2546        const betweenOption = Array.from(options).find(opt => opt.textContent.trim() === 'Между');
2547        
2548        if (!betweenOption) {
2549            console.error('Опция "Между" не найдена');
2550            return;
2551        }
2552
2553        betweenOption.click();
2554        console.log('Клик на "Между" выполнен');
2555        await wait(1500);
2556        
2557        // Устанавливаем значения "от" и "до"
2558        const allLabels = document.querySelectorAll('label');
2559        let fromInput = null;
2560        let toInput = null;
2561        
2562        for (const label of allLabels) {
2563            const text = label.textContent.trim();
2564            if (text === 'Значение от') {
2565                const inputId = label.getAttribute('for');
2566                if (inputId) {
2567                    fromInput = document.getElementById(inputId);
2568                }
2569            } else if (text === 'Значение до') {
2570                const inputId = label.getAttribute('for');
2571                if (inputId) {
2572                    toInput = document.getElementById(inputId);
2573                }
2574            }
2575        }
2576        
2577        if (!fromInput || !toInput) {
2578            console.error('Поля "от" и "до" не найдены');
2579            return;
2580        }
2581
2582        // Устанавливаем "от" = 1
2583        fromInput.focus();
2584        fromInput.value = '1';
2585        fromInput.dispatchEvent(new Event('input', { bubbles: true }));
2586        fromInput.dispatchEvent(new Event('change', { bubbles: true }));
2587        console.log('Установлено значение "от" = 1');
2588        await wait(500);
2589        
2590        // Устанавливаем "до" = 4
2591        toInput.focus();
2592        toInput.value = '4';
2593        toInput.dispatchEvent(new Event('input', { bubbles: true }));
2594        toInput.dispatchEvent(new Event('change', { bubbles: true }));
2595        console.log('Установлено значение "до" = 4');
2596        await wait(1000);
2597        
2598        // Выделяем отфильтрованные кластеры
2599        showStatus('Выделение отфильтрованных кластеров...');
2600        
2601        // Сначала кликаем на первый чекбокс в списке кластеров
2602        const firstClusterCheckbox = document.querySelector('tbody input[type="checkbox"]');
2603        if (firstClusterCheckbox) {
2604            firstClusterCheckbox.click();
2605            console.log('Клик на первый чекбокс кластера выполнен');
2606            await wait(500);
2607        }
2608        
2609        // Теперь кликаем на общий чекбокс для выделения всех
2610        let selectAllCheckbox2 = document.querySelector('.css-1ytbthu .css-vlug8u');
2611        if (!selectAllCheckbox2) {
2612            selectAllCheckbox2 = document.querySelector('thead .css-vlug8u');
2613        }
2614        if (!selectAllCheckbox2) {
2615            const checkboxes2 = document.querySelectorAll('input[type="checkbox"]');
2616            if (checkboxes2.length > 0) {
2617                selectAllCheckbox2 = checkboxes2[0];
2618            }
2619        }
2620        
2621        if (!selectAllCheckbox2) {
2622            console.error('Checkbox для отфильтрованных кластеров не найден');
2623            return;
2624        }
2625
2626        selectAllCheckbox2.click();
2627        console.log('Клик на checkbox отфильтрованных кластеров выполнен');
2628        await wait(1000);
2629        
2630        // Открываем меню "Действия"
2631        showStatus('Открытие меню действий для отфильтрованных кластеров...');
2632        const actionsButton2 = document.querySelector('.css-1rll63h');
2633        if (!actionsButton2) {
2634            console.error('Кнопка "Действия" не найдена');
2635            return;
2636        }
2637
2638        actionsButton2.click();
2639        await wait(300);
2640        
2641        // Кликаем на "Управление"
2642        const managementButtons2 = document.querySelectorAll('.css-hq58ok');
2643        if (managementButtons2.length < 2) {
2644            console.error('Кнопка "Управление" не найдена');
2645            return;
2646        }
2647
2648        managementButtons2[1].click();
2649        await wait(300);
2650        
2651        // Кликаем на "Стратегия"
2652        const strategyTabs2 = document.querySelectorAll('.css-582wun');
2653        if (strategyTabs2.length < 3) {
2654            console.error('Вкладка "Стратегия" не найдена');
2655            return;
2656        }
2657
2658        strategyTabs2[2].click();
2659        await wait(300);
2660        
2661        // Вставляем стратегию УДЕРЖАНИЯ МЕСТА
2662        showStatus('Вставка стратегии удержания места...');
2663        const clusterInsertButtons2 = document.querySelectorAll('.css-5kbhos');
2664        let clusterInsertButton2 = null;
2665        
2666        // Собираем все кнопки "Вставить стратегию"
2667        const insertStrategyButtons2 = [];
2668        for (const btn of clusterInsertButtons2) {
2669            if (btn.textContent.includes('Вставить стратегию')) {
2670                insertStrategyButtons2.push(btn);
2671            }
2672        }
2673        
2674        // Берем вторую кнопку (индекс 1)
2675        if (insertStrategyButtons2.length >= 2) {
2676            clusterInsertButton2 = insertStrategyButtons2[1];
2677            console.log('Используем вторую кнопку "Вставить стратегию" для отфильтрованных кластеров');
2678        } else if (insertStrategyButtons2.length === 1) {
2679            clusterInsertButton2 = insertStrategyButtons2[0];
2680            console.log('Найдена только одна кнопка, используем её');
2681        }
2682        
2683        if (!clusterInsertButton2) {
2684            console.error('Кнопка "Вставить стратегию" для отфильтрованных кластеров не найдена');
2685            return;
2686        }
2687
2688        // Получаем стратегию УДЕРЖАНИЯ МЕСТА
2689        const holdPositionClusterStrategyCode = await getHoldPositionClusterStrategy();
2690        console.log('Используем стратегию удержания места, длина:', holdPositionClusterStrategyCode.length);
2691        
2692        try {
2693            await navigator.clipboard.writeText(holdPositionClusterStrategyCode);
2694            console.log('✓ Стратегия удержания места скопирована');
2695        } catch {
2696            await GM.setClipboard(holdPositionClusterStrategyCode);
2697            console.log('✓ Стратегия удержания места скопирована через GM');
2698        }
2699        
2700        await wait(500);
2701        
2702        clusterInsertButton2.click();
2703        console.log('Клик на "Вставить стратегию" удержания места выполнен');
2704        await wait(1000);
2705        
2706        // Находим поле для ввода ставки
2707        const clusterInputLabels2 = Array.from(document.querySelectorAll('.MuiInputLabel-root'));
2708        let clusterTargetInput2 = null;
2709        
2710        // Ищем второй input с меткой "Желаемое значение За корзину"
2711        let foundInputs2 = [];
2712        for (const label of clusterInputLabels2) {
2713            const labelText = label.textContent.trim();
2714            if (labelText.includes('Желаемое значение За корзину')) {
2715                const inputId = label.getAttribute('for');
2716                if (inputId) {
2717                    const input = document.getElementById(inputId);
2718                    if (input) {
2719                        foundInputs2.push(input);
2720                        console.log(`Найдено поле для отфильтрованных кластеров: ${labelText}, id: ${inputId}`);
2721                    }
2722                }
2723            }
2724        }
2725        
2726        // Берем второй найденный input (индекс 1)
2727        if (foundInputs2.length >= 2) {
2728            clusterTargetInput2 = foundInputs2[1];
2729            console.log(`Используем второй input для отфильтрованных кластеров: ${clusterTargetInput2.id}`);
2730        } else if (foundInputs2.length === 1) {
2731            clusterTargetInput2 = foundInputs2[0];
2732            console.log(`Найден только один input, используем его: ${clusterTargetInput2.id}`);
2733        }
2734
2735        if (!clusterTargetInput2) {
2736            const clusterInputs2 = document.querySelectorAll('input[type="number"]');
2737            for (const input of clusterInputs2) {
2738                const name = input.getAttribute('name') || '';
2739                if (name.includes('CostPerAddedToCart') || name.includes('value')) {
2740                    clusterTargetInput2 = input;
2741                    break;
2742                }
2743            }
2744        }
2745        
2746        if (clusterTargetInput2) {
2747            clusterTargetInput2.focus();
2748            clusterTargetInput2.value = cartCostRounded.toString();
2749            clusterTargetInput2.dispatchEvent(new Event('input', { bubbles: true }));
2750            clusterTargetInput2.dispatchEvent(new Event('change', { bubbles: true }));
2751            console.log(`Значение ${cartCostRounded} установлено для отфильтрованных кластеров в поле ${clusterTargetInput2.id}`);
2752            await wait(500);
2753        }
2754        
2755        // Нажимаем "Применить"
2756        showStatus('Применение стратегии удержания места...');
2757        const clusterStrategyApplyButtons2 = document.querySelectorAll('.css-eqlbov');
2758        if (clusterStrategyApplyButtons2.length >= 2) {
2759            clusterStrategyApplyButtons2[1].click();
2760            console.log('Клик на "Применить" стратегию удержания места выполнен');
2761            await wait(1000);
2762            
2763            // Нажимаем "Сохранить"
2764            showStatus('Сохранение стратегии удержания места...');
2765            const saveButton = document.querySelector('.css-tn31lt');
2766            if (saveButton && saveButton.textContent.trim() === 'Сохранить') {
2767                saveButton.click();
2768                console.log('Клик на "Сохранить" стратегию удержания места выполнен');
2769                await wait(1000);
2770            } else {
2771                console.error('Кнопка "Сохранить" для стратегии удержания места не найдена');
2772            }
2773            
2774            // Закрываем модальное окно
2775            const closeModalButtons2 = document.querySelectorAll('button[aria-label="Close"]');
2776            if (closeModalButtons2.length > 0) {
2777                closeModalButtons2[closeModalButtons2.length - 1].click();
2778                console.log('Модальное окно закрыто');
2779                await wait(1000);
2780            }
2781        }
2782    }
2783
2784    // Функция для применения автофильтров
2785    async function applyAutofilters() {
2786        showStatus('Открытие автофильтров...');
2787        
2788        const autofilterAccordion = document.getElementById('bidder-constructor');
2789        if (!autofilterAccordion) {
2790            console.error('Аккордеон "Автофильтры" не найден');
2791            return;
2792        }
2793
2794        const accordionButton = autofilterAccordion.querySelector('button[aria-expanded]');
2795        const isExpanded = accordionButton && accordionButton.getAttribute('aria-expanded') === 'true';
2796        
2797        if (!isExpanded && accordionButton) {
2798            accordionButton.click();
2799            console.log('Аккордеон "Автофильтры" раскрыт');
2800            await wait(1000);
2801        }
2802        
2803        // Кликаем на "Шаблоны"
2804        showStatus('Открытие шаблонов...');
2805        const templatesButtons = autofilterAccordion.querySelectorAll('button');
2806        let templateButton = null;
2807        
2808        for (const btn of templatesButtons) {
2809            if (btn.textContent.trim() === 'Шаблоны') {
2810                templateButton = btn;
2811                break;
2812            }
2813        }
2814        
2815        if (!templateButton) {
2816            console.error('Кнопка "Шаблоны" не найдена');
2817            return;
2818        }
2819
2820        templateButton.click();
2821        console.log('Кнопка "Шаблоны" выбрана');
2822        await wait(500);
2823        
2824        // Выбираем "Расширение"
2825        showStatus('Выбор шаблона "Расширение"...');
2826        const allElements = document.querySelectorAll('div, button, span, p');
2827        let extensionTemplate = null;
2828        
2829        for (const el of allElements) {
2830            const text = el.textContent.trim();
2831            if (text === 'Расширение') {
2832                extensionTemplate = el;
2833                break;
2834            }
2835        }
2836        
2837        if (!extensionTemplate) {
2838            console.error('Шаблон "Расширение" не найден');
2839            return;
2840        }
2841
2842        extensionTemplate.click();
2843        console.log('Шаблон "Расширение" выбран');
2844        await wait(500);
2845        
2846        // Сохраняем
2847        showStatus('Сохранение автофильтров...');
2848        const saveButtonsAfterTemplate = document.querySelectorAll('button');
2849        let saveAutofilterButton = null;
2850        
2851        for (const btn of saveButtonsAfterTemplate) {
2852            if (btn.textContent.trim() === 'Сохранить') {
2853                saveAutofilterButton = btn;
2854                break;
2855            }
2856        }
2857        
2858        if (!saveAutofilterButton) {
2859            console.error('Кнопка "Сохранить" не найдена');
2860            return;
2861        }
2862
2863        saveAutofilterButton.click();
2864        console.log('Клик на "Сохранить" автофильтры выполнен');
2865        await wait(1000);
2866        
2867        // Применяем автофильтры вручную
2868        showStatus('Применение автофильтров вручную...');
2869        const applyButtonsAfterSave = document.querySelectorAll('button');
2870        let applyAutofilterButton = null;
2871        
2872        for (const btn of applyButtonsAfterSave) {
2873            if (btn.textContent.trim() === 'Применить автофильтры вручную') {
2874                applyAutofilterButton = btn;
2875                break;
2876            }
2877        }
2878        
2879        if (!applyAutofilterButton) {
2880            console.error('Кнопка "Применить автофильтры вручную" не найдена');
2881            return;
2882        }
2883
2884        applyAutofilterButton.click();
2885        console.log('Клик на "Применить автофильтры вручную" выполнен');
2886        await wait(1000);
2887    }
2888
2889    // Функция для обработки ошибок и перехода к следующей кампании
2890    async function handleStrategyError() {
2891        const savedDRR = await GM.getValue('bulkProcessingDRR', null);
2892        if (savedDRR !== null) {
2893            console.log('Обнаружена ошибка при массовой обработке, ждем 10 секунд');
2894            showStatus('⚠️ Ошибка! Переход к следующей кампании через 10 секунд...', true);
2895            
2896            for (let i = 10; i > 0; i--) {
2897                showStatus(`⚠️ Ошибка! Переход к следующей через ${i} сек...`, true);
2898                await wait(1000);
2899            }
2900            
2901            const campaignsJson = await GM.getValue('bulkCampaigns', null);
2902            const currentIndex = await GM.getValue('bulkCurrentIndex', 0);
2903            const totalCampaigns = await GM.getValue('bulkTotalCampaigns', 0);
2904            
2905            if (campaignsJson) {
2906                const campaigns = JSON.parse(campaignsJson);
2907                const nextIndex = currentIndex + 1;
2908                
2909                console.log(`Обработано кампаний: ${nextIndex} из ${totalCampaigns}`);
2910                
2911                if (nextIndex < campaigns.length) {
2912                    await GM.setValue('bulkCurrentIndex', nextIndex);
2913                    console.log(`Переходим к кампании ${nextIndex + 1}: ${campaigns[nextIndex]}`);
2914                    // Просто перенаправляем текущую вкладку на следующую кампанию
2915                    window.location.href = campaigns[nextIndex];
2916                } else {
2917                    console.log('Все кампании обработаны');
2918                    await GM.deleteValue('bulkProcessingDRR');
2919                    await GM.deleteValue('bulkCampaigns');
2920                    await GM.deleteValue('bulkCurrentIndex');
2921                    await GM.deleteValue('bulkTotalCampaigns');
2922                    
2923                    showStatus('✅ Все кампании обработаны!');
2924                    alert('✅ Все кампании обработаны!');
2925                }
2926            }
2927        }
2928    }
2929
2930    // Инициализация
2931    function init() {
2932        console.log('Инициализация расширения');
2933        
2934        if (window.location.href.includes('/advert/campaigns')) {
2935            console.log('Страница списка кампаний обнаружена');
2936            setTimeout(() => {
2937                if (document.body) {
2938                    createBulkUI();
2939                } else {
2940                    console.error('Body не найден');
2941                }
2942            }, 1000);
2943        } else if (window.location.href.includes('/campaigns/auto-campaigns/') && window.location.href.includes('/campaign')) {
2944            console.log('Страница кампании обнаружена');
2945            setTimeout(() => {
2946                if (document.body) {
2947                    createUI();
2948                } else {
2949                    console.error('Body не найден');
2950                }
2951            }, 1000);
2952        } else {
2953            console.log('Не на странице кампании, UI не создается');
2954        }
2955    }
2956
2957    // Запускаем инициализацию
2958    init();
2959
2960})();