[{"data":1,"prerenderedAt":281},["ShallowReactive",2],{"project-ru-product-image-editor":3,"recommendation-mention-sources":221},{"id":4,"title":5,"body":6,"category":177,"context":178,"cover":179,"coverAlt":180,"demo":181,"description":182,"extension":183,"featured":184,"locale":185,"meta":186,"navigation":184,"order":187,"path":188,"published":184,"repository":181,"results":189,"role":202,"seo":203,"slug":204,"stack":205,"stem":218,"year":219,"__hash__":220},"projects\u002Fru\u002Fprojects\u002Fproduct-image-editor.md","Редактор товарной инфографики в админке inSales на Vue",{"type":7,"value":8,"toc":161},"minimark",[9,14,18,21,25,28,37,41,46,49,61,65,68,71,75,78,85,88,92,95,101,104,108,111,117,121,137,141],[10,11,13],"h2",{"id":12},"задача","Задача",[15,16,17],"p",{},"В карточке товара inSales для работы с фото был только диалог на CropperJS: картинку можно было обрезать, и всё. Инфографику с заголовком, плашками и чистым фоном продавцы делали в другом сервисе, скачивали и загружали обратно.",[15,19,20],{},"Нужен был редактор, который открывается прямо из карточки и закрывает задачу целиком: собрать картинку, при необходимости обработать её с помощью AI, сохранить проект редактируемым и вернуть готовое изображение в каталог.",[10,22,24],{"id":23},"моя-роль","Моя роль",[15,26,27],{},"Frontend продукта был на мне. Спроектировал архитектуру Vue-приложения, сверстал интерфейс по готовым макетам из Figma, подключил библиотеку редактора и согласовал API-контракты с backend-разработчиком, который делал серверную часть. Ещё писал технические задания и сценарии для QA, добавил трекинг AI-действий в Mixpanel и готовил описания новых функций для поддержки. В команде были продакт, дизайнер, backend-разработчик и тестировщик.",[15,29,30,31,36],{},"Сам canvas работает на ",[32,33,35],"a",{"href":34},"\u002Fru\u002Fwork\u002Fimage-editor\u002F","моей отдельной библиотеке на TypeScript и FabricJS",". Здесь речь о продукте поверх неё: панели, диалоги, серверные сценарии, лимиты, ошибки и всё, что происходит между кликом и сохранённым товаром.",[10,38,40],{"id":39},"что-я-сделал","Что я сделал",[42,43,45],"h3",{"id":44},"два-сохранения-и-два-состояния-проекта","Два сохранения и два состояния проекта",[15,47,48],{},"У сохранения две границы. Продавец жмёт «Сохранить» в редакторе, а потом должен сохранить и саму карточку товара. Если он закроет карточку без сохранения, новая картинка не применится. И её редактируемый проект не должен заменить тот, что соответствует опубликованному изображению.",[15,50,51,52,56,57,60],{},"Вместе с backend-разработчиком договорились о модели из двух состояний. Сохранение в редакторе создаёт новую версию картинки и кладёт проект в ",[53,54,55],"code",{},"draft_state",". Сохранение карточки переводит черновик в ",[53,58,59],{},"origin_state",". Редактор всегда открывает подтверждённое состояние, поэтому брошенная правка не перезапишет то, что продавец действительно опубликовал.",[42,62,64],{"id":63},"разделил-корневой-компонент-по-сценариям","Разделил корневой компонент по сценариям",[15,66,67],{},"С новыми функциями корневой диалог разросся примерно до 3 500 строк. Я разнёс логику по 22 composables: сессия и runtime, жизненный цикл изображения, работа с canvas, шаблоны, AI и массовый перенос.",[15,69,70],{},"Главное ограничение — одновременно живут два редактора: видимый и скрытый, который нужен для массового переноса. Поэтому composables работают с конкретной сессией редактора. Видимый редактор использует одну, массовый перенос создаёт для скрытого свою. Фоновая обработка не может изменить то, что продавец видит на экране.",[42,72,74],{"id":73},"долгие-операции-с-понятными-состояниями","Долгие операции с понятными состояниями",[15,76,77],{},"Сохранение — это цепочка шагов: экспорт, проверка размера, загрузка частями для файлов больше 10 МБ, серверная обработка с polling, итоговый URL и замена фото в галерее товара. На всё уходит примерно 5–10 секунд. Всё это время редактор заблокирован, чтобы продавец не менял версию, которую сервер ещё обрабатывает.",[15,79,80],{},[81,82],"img",{"alt":83,"src":84},"Редактор во время AI-удаления фона: на изображении индикатор обработки, панель инструментов неактивна","\u002Fimages\u002Fwork\u002Fproduct-image-editor\u002Fai-processing-locked-editor.webp",[15,86,87],{},"AI-действия устроены так же. Vue ставит редактирование на паузу, показывает прогресс прямо на картинке, опрашивает сервер, затем подставляет результат с прежними размерами и положением и обновляет остаток запросов. Окно запроса для генерации текста сбрасывается при смене выделения: текст, написанный для одного блока, не попадёт в другой.",[42,89,91],{"id":90},"массовый-перенос-до-10-изображений-за-раз","Массовый перенос — до 10 изображений за раз",[15,93,94],{},"Продавец оформляет одну фотографию и переносит композицию на другие фото товара, до 10 за раз, при желании с удалением фона. Для каждой выбранной фотографии скрытый редактор применяет размеры исходного изображения, восстанавливает композицию, сохраняет редактируемый проект и итоговую картинку и очищается перед следующей.",[15,96,97],{},[81,98],{"alt":99,"src":100},"Режим массового переноса: под исходной композицией выбраны три фото товара, включён переключатель «Cut out the background»","\u002Fimages\u002Fwork\u002Fproduct-image-editor\u002Fbulk-transfer-select-targets.webp",[15,102,103],{},"Отмена тоже должна быть безопасной. Если фото уже в обработке, очередь остановится только после него, а необработанные снимаются сразу. Если исходная композиция изменилась, когда продавец уже выбирает фото, режим переноса закрывается, чтобы не применить устаревшее состояние.",[42,105,107],{"id":106},"один-редактор-в-двух-местах-продукта","Один редактор в двух местах продукта",[15,109,110],{},"Сначала редактор был завязан на медиа товара. Чтобы использовать его в визуальном редакторе сайта, я вынес товарную логику за пределы компонента. Теперь каждое место, откуда открывается редактор, передаёт тип сущности, нормализованные данные изображения, список доступных картинок, обработчик сохранения и рекомендуемые пропорции crop. В визуальном редакторе один экземпляр диалога монтируется на верхнем уровне, а набор функций зависит от контекста: генерация текста по данным товара есть только в карточке, а при правке картинки сайта создаётся новый файл, исходный остаётся как был.",[15,112,113],{},[81,114],{"alt":115,"src":116},"Тот же редактор, открытый из визуального редактора сайта: обрезка баннера по рекомендуемой пропорции","\u002Fimages\u002Fwork\u002Fproduct-image-editor\u002Fsite-editor-banner-crop.webp",[10,118,120],{"id":119},"результат","Результат",[122,123,124,128,131,134],"ul",{},[125,126,127],"li",{},"Редактором пользуются больше 3 000 активных клиентов inSales — это данные продуктовой аналитики.",[125,129,130],{},"Через редактор проходит 800+ AI-операций в день: быстрое и точное удаление фона, улучшение качества, генерация текста.",[125,132,133],{},"Одни и те же правки для 10 изображений вручную занимали 5–10 минут, с массовым переносом — 2–3 минуты. Функция вышла в июле 2026 года.",[125,135,136],{},"С сентября 2026 года тот же компонент редактирует картинки в визуальном редакторе сайта, то есть один редактор работает в двух production-сценариях.",[10,138,140],{"id":139},"где-попробовать","Где попробовать",[15,142,143,144,147,148,154,155,160],{},"Редактор сделан только для десктопа: проверял его в Chrome, Firefox и Safari на Windows и macOS, а на мобильных кнопка открытия скрыта. Попробовать редактор может любой: зарегистрируйте магазин на inSales, добавьте товар, загрузите фото и откройте редактор из карточки товара в браузере на компьютере. Без регистрации можно попробовать ",[32,145,146],{"href":34},"open-source движок",", на котором он работает: открыть ",[32,149,153],{"href":150,"rel":151},"https:\u002F\u002Fanu3ev.github.io\u002Fimage-editor\u002F",[152],"nofollow","живое демо"," или посмотреть ",[32,156,159],{"href":157,"rel":158},"https:\u002F\u002Fgithub.com\u002FAnu3ev\u002Fimage-editor",[152],"исходный код на GitHub",".",{"title":162,"searchDepth":163,"depth":163,"links":164},"",2,[165,166,167,175,176],{"id":12,"depth":163,"text":13},{"id":23,"depth":163,"text":24},{"id":39,"depth":163,"text":40,"children":168},[169,171,172,173,174],{"id":44,"depth":170,"text":45},3,{"id":63,"depth":170,"text":64},{"id":73,"depth":170,"text":74},{"id":90,"depth":170,"text":91},{"id":106,"depth":170,"text":107},{"id":119,"depth":163,"text":120},{"id":139,"depth":163,"text":140},"Браузерные редакторы","inSales","\u002Fimages\u002Fwork\u002Fproduct-image-editor\u002Fuser-template-created.webp","Редактор изображений inSales с открытой панелью «Мои шаблоны» и инфографикой с кроссовками на холсте сразу после создания шаблона",null,"Полноэкранный Vue-редактор, в котором продавцы собирают инфографику для товаров из шаблонов и с помощью AI. Им пользуются больше 3 000 активных клиентов inSales, AI-операций — 800+ в день.","md",true,"ru",{},1,"\u002Fru\u002Fprojects\u002Fproduct-image-editor",[190,193,196,199],{"value":191,"label":192},"3 000+","активных клиентов inSales пользуются редактором (по продуктовой аналитике)",{"value":194,"label":195},"800+","AI-операций в день в редакторе, включая удаление фона и генерацию текста",{"value":197,"label":198},"2–3 мин","на одни и те же правки для 10 фото товара через массовый перенос вместо 5–10 мин вручную",{"value":200,"label":201},"2","сценария в продакшене у одного компонента: карточка товара и визуальный редактор сайта","Отвечал за frontend продукта, интеграцию редактора и API-контракты",{"title":5,"description":182},"product-image-editor",[206,207,208,209,210,211,212,213,214,215,216,217],"Vue 3","TypeScript","FabricJS","Complex UI","Composition API","E-Commerce Development","Frontend Architecture","SCSS","Web Application Development","API Integration","AI-Powered Image Editing","Front-End Development","ru\u002Fprojects\u002Fproduct-image-editor","Март 2025 – сентябрь 2026","iXYxLA-ud7wj9pxeKZazgn8O7LCdzeH3V2hbjo29bCY",[222,232,237,252,261,266,271,276],{"stem":223,"name":224,"date":225,"featured":163,"published":184,"mentions":226},"recommendations\u002Fandrey-stikheev","Andrey Stikheev","2026-09-08",[227,229],{"project":204,"quote":228},"Among his most notable projects was a sophisticated browser-based image editor built with TypeScript and Fabric.js, now used by thousands of merchants.",{"project":230,"quote":231},"abandoned-carts","He also developed the frontend for a paid abandoned-cart product and contributed to the production migration from Vue 2 to Vue 3.",{"stem":233,"name":234,"date":235,"featured":181,"published":184,"mentions":236},"recommendations\u002Fdaniil-churakov","Daniil Churakov","2026-08-27",[],{"stem":238,"name":239,"date":240,"featured":170,"published":184,"mentions":241},"recommendations\u002Fdmitry-sadovsky","Dmitry Sadovsky","2026-08-22",[242,245,247,250],{"project":243,"quote":244},"visual-storefront","For years he was the driving force behind our visual storefront editor — a large, complex application where merchants build their online stores.",{"project":204,"quote":246},"It became the tool merchants use to design product images right inside the admin panel — the kind of component companies usually buy rather than build.",{"project":248,"quote":249},"image-editor","What impressed me most was the infographic editor he built essentially from scratch: a full canvas-based graphic editor with artboards, shapes, text styling, templates, and undo\u002Fredo history, powered by an editor core he developed himself.",{"project":230,"quote":251},"Our abandoned carts functionality — with multi-channel customer messaging, communication history, and analytics — was largely his work, from UI down to the details of how requests are cancelled and states stay in sync.",{"stem":253,"name":254,"date":255,"featured":187,"published":184,"mentions":256},"recommendations\u002Fegor-fedkin","Egor Fedkin","2026-08-31",[257,259],{"project":204,"quote":258},"Today, the tool is actively used by around 3,000 users.",{"project":230,"quote":260},"It has already generated approximately twice the revenue needed to cover its development costs.",{"stem":262,"name":263,"date":264,"featured":181,"published":184,"mentions":265},"recommendations\u002Femmanuel-stephen","Emmanuel Stephen","2026-10-11",[],{"stem":267,"name":268,"date":269,"featured":181,"published":184,"mentions":270},"recommendations\u002Fevgeny-lonshakov","Евгений Лоншаков","2026-09-21",[],{"stem":272,"name":273,"date":274,"featured":181,"published":184,"mentions":275},"recommendations\u002Froman-gorbachev","Роман Горбачев","2026-09-17",[],{"stem":277,"name":278,"date":279,"featured":181,"published":184,"mentions":280},"recommendations\u002Fvladimir-bedarev","Bedarev Vladimir","2026-09-16",[],1793195987433]