جامعترین سند تجربه کاربری Workflow Builder: چیدمان کانواس، سیمکشی، پالت گرهها، پنل پیکربندی پویا، انتخاب متغیر، اجرای آزمایشی، نمایش خطا، کیبورد شورتکاتها، فهرست کامل کامپوننتها، معماری فنی در Nuxt و معیارهای سنجش موفقیت.
کل طراحی Builder تحت تأثیر یک واقعیت قرار دارد: کاربر این محصول، برنامهنویس نیست. مدیر فروش، بازاریاب یا صاحب کسبوکار باید بدون آموزش بتواند جریان بسازد. پس «سادگی» اولویت اول است و «امکانات» دوم.
پیشفرض ساده؛ گزینههای پیشرفته در accordion پنهان. ۸۰٪ کاربران هرگز آنها را نخواهند دید.
صفحه هرگز خالی و بیمعنا نیست. همیشه یک نقطه شروع، قالب آماده یا راهنمای روی صفحه هست.
به هر کلیک، بکشید و رها کردن باید فوراً بازخورد بصری برسد؛ بدون این، احساس کندی میشود.
هیچ خطایی غیرقابل ترمیم نیست. هر خطا پیام + راهحل + دکمه بازیابی مستقیم دارد.
برچسب «Action» ندهید؛ بگویید «ارسال پیامک به مشتری جدید». همه چیز با زبان کاربر توضیح داده میشود.
کشیدن، رها کردن، بستن، ذخیره — همه رفتارها ثابت و یکسان در کل پنل هستند.
| شخصیت | نقش | هدف اصلی | بزرگترین ترس | تعداد مواجهه |
|---|---|---|---|---|
| فرهاد فروشنده | کارشناس فروش | پیگیری سریع لیدهای گرم بدون گم شدن | زیادهروی در فرمها و تنظیمات پیچیده | روزانه (بسیار بالا) |
| مریم مدیر بازاریابی | بازاریاب | ساخت کمپین و اتوماسیون ایمیلی بدون کمک تیم فنی | «نمیدونم متغیر کجا قرار بگیره» | هفتگی |
| سامان مدیرعامل | مدیر | داشبورد + دیدن اینکه چه چیزی خودکار انجام میشود | شلوغی و نبود جمعبندی ساده | ماهانه |
| نوید توسعهدهنده مشتری | فنی / API | اتصال سیستم داخلی از طریق Webhook و HTTP | نبود مستندات و محدودیت بیش از حد | فقط هنگام راهاندازی |
| ارشاد پشتیبانی | تیم ما | پیدا کردن سریع دلیل شکست یک جریان | نبود لاگ و ابزار دیباگ | روزانه |
صفحه Builder از پنج ناحیه ثابت تشکیل شده است. ناحیهها هرگز جابهجا نمیشوند تا ماهیچه حافظه کاربر شکل گیرد.
┌─────────────────────────────────────────────────────────────────────────────┐
│ ② Top Bar │
│ [← بازگشت] [نام جریان ▾] [● پیشنویس] [🔍 جستوجو] [↶ ↷] │
│ [ذخیره] [آزمایش] [انتشار] │
├──────────┬──────────────────────────────────────────────────┬───────────────┤
│ │ │ │
│ ① Left │ ③ Canvas │ ④ Right │
│ Palette │ (مرکز، قابل بزرگنمایی) │ Config Panel │
│ │ │ │
│ 🔍 جستوجو│ ┌──────┐ ┌──────┐ │ [گره انتخابشده]│
│ │ │ Trigger│────►│ HTTP │ │ ─────────── │
│ ▸ محرکها │ └──────┘ └──────┘ │ URL │
│ ▸ اقدامها │ ┌──────┐ │ [{{ }} ] │
│ ▸ شرطها │ ┌─────┐ │Email │ │ ─────────── │
│ ▸ داده │ │ IF │──────►│ │ │ Error │
│ │ └─────┘ └──────┘ │ -policy │
│ │ │ │
├──────────┴──────────────────────────────────────────────────┴───────────────┤
│ ⑤ Bottom Bar │
│ وضعیت: ذخیره شد ۲ ثانیه قبل │ ۴ گره │ آخرین اجرا: موفق ۱۲:۳۰ │ 🐞 آزمایش │
└─────────────────────────────────────────────────────────────────────────────┘
| # | ناحیه | عرض/ارتفاع | محتوا | رفتار بستن |
|---|---|---|---|---|
| ① | پالت چپ (Palette) | ۲۸۰px (قابل جمع شدن تا ۵۶px) | دستهبندی گرهها + جستوجو + کشیدن | جمع شدن با دکمه و P |
| ② | نوار بالا (Top Bar) | ۵۶px ثابت | نام، وضعیت، undo/redo، ذخیره، انتشار | بدون امکان بستن |
| ③ | کانواس (Canvas) | انعطافپذیر | گراف + سیمها + زوم | — |
| ④ | پنل راست (Config) | ۳۶۰px (قابل جمع شدن) | فرم پیکربندی گره انتخابشده | با Esc یا کلیک روی خالی بودن |
| ⑤ | نوار پایین (Status) | ۴۰px | وضعیت ذخیره، تعداد گره، آخرین اجرا | بدون امکان بستن |
┌─────────────────────────────────┐
│ ● ① آیکون نوع [جداشده] ② │ ← هدر رنگی، برچسب نوع
│─────────────────────────────────│
│ ③ عنوان کاربری │ ← «ارسال پیامک» (قابل ویرایش دوبار کلیک)
│ ④ خلاصه مقدارها │ ← «به ۰۹۱۲… · قالب: خوشآمد»
│─────────────────────────────────│
│ ⚠ ⑤ نشان خطا (در صورت وجود) │
└─────────────────────────────────┘
⑥ ورودی (چپ) ⑦ خروجی (راست)
◯ ........................◯
⑧ دسته اتصال: دایرهای همیشه در لبه، هیچوقت وسط گره
| رفتار | عملکرد | بازخورد |
|---|---|---|
| کلیک | انتخاب گره + باز شدن پنل پیکربندی | حاصلشدن حاشیه ۲px آبی |
| کلیک دوباره | ویرایش مستقیم عنوان گره | تبدیل به Input با حاشیه فعال |
| درگ (کشیدن) | جابهجایی گره — Snap به شبکه ۸px | سایه روشن هنگام هل دادن + نمایش X/Y |
| Shift + درگ | جابهجایی آزاد بدون Snap | خطچاک عمودی راهنما |
| کلیک دوبار روی لبه پایین | افزودن سریع گره جدید بعدی (کوتاهترین مسیر) | نمایش مودال کوچک انتخاب گره |
| Ctrl/Cmd + کلیک | انتخاب چندگانه گرهها | شمای چندگانه با حاشیه نقطهچین |
| Del | حذف گره (با تأیید اگر فعال باشد) | Toast با دکمه Undo ۵ ثانیهای |
پالت، ویترین کل گرههاست. اگر کاربر نتواند در ۱۰ ثانیه گره درست را پیدا کند، طراحی شکست خورده است.
┌────────────────────────────┐ │ 🔍 جستوجوی گره... [⌘K]│ │────────────────────────────│ │ ✦ پیشنهادی برای شما │ ← بر اساس گرههای موجود │ [ارسال ایمیل] [پیامک] │ │────────────────────────────│ │ ▸ محرکها (۸) │ ← جمعشده بهصورت پیشفرض │ ▸ CRM │ │ ▸ فرم وب │ │ ▸ زمانبندی │ │ ▾ اقدامها (۹) │ ← باز │ crm.contact.create │ ← کارت با آیکون + نام فارسی │ crm.contact.update │ │ crm.deal.move_stage │ │ ▸ HTTP و داده │ │ ▸ پیامرسان │ │ ▸ شرطها (۵) │ │ ▸ پیکربندی جریان (۳) │ │────────────────────────────│ │ 💡 «گره مورد نیافتید؟» │ │ درخواست گره جدید │ └────────────────────────────┘
| عنصر | رفتار | توضیح |
|---|---|---|
| جستوجو | فیلتر زنده با debounce ۱۵۰ms | هم بر اساس اسلاگ انگلیسی، هم برچسب فارسی و توضیحات |
| کارتهای گره | درگ + رها روی کانواس | آیکون + نام فارسی + توضیح کوتاه یکخطی |
| گرههای غیرفعال | طوسی + بج «ماژول لازم» | کلیک ⇒ مودال ارتقای پلن / نصب ماژول |
| تعداد دسته | نمایش عددی پشت هر دسته | به کاربر نشان میدهد چه امکاناتی دارد |
| کلید ⌘K | Command Palette عمومی | جستوجوی سراسری در همه گرهها + کارها |
| حالت «پیشنهادی» | ۳ گره پرکاربرد بالای پالت | بر اساس وضعیت فعلی جریان محاسبه میشود |
(درگ از دسته خروجی) (هنگام رها کردن)
① ◯──┐ ┌──◯ ② ◯──┐
│ ② سیم متحرک با نوک │ ④ خط خطا
│ دنبالکننده │ قرمز اگر نامعتبر
▼ ▼
[گره منبع] ····◯(ghost)····► [گره مقصد معتبر]
③ Snap به دسته ورودی با بزرگنمایی
| مرحله | رفتار | بازخورد بصری |
|---|---|---|
| ۱) شروع درگ از دسته | دسته بزرگ میشود + سیم شناور پدیدار میشود | دسته: ۸px → ۱۴px + هاله |
| ۲) حرکت | سیم با خم منحنی Bezier به نوک موس دنبال میشود | دستههای واجد شرایط نزدیک چشمک میزنند |
| ۳) نزدیک شدن | Snap خودکار به دسته ورودی معتبر | حلقه نارنجی دور دسته مقصد |
| ۴) رها کردن روی مقصد نامعتبر | اتصال انجام نمیشود | لرزش خفیف + tooltip «اتصال مجاز نیست» |
| ۵) رها کردن روی مقصد معتبر | ساخت یال + ذخیره خودکار | انیمیشن نبض + Toast «اتصال ایجاد شد» |
| ۶) حذف سیم | کلیک وسط سیم + Del یا کلیک راست | menu: حذف / برعکس کردن |
قواعد اعتبارسنجی هنگام سیمکشی:
۱) نوع خروجی سازگار با نوع ورودی؟
├─ همه → همه ⇒ مجاز (پیشفرض)
└─ شرط دارای خروجیهای TRUE/FALSE ⇒ مجاز فقط به گره بعدی
۲) اتصال خود-به-خود؟ (self-loop)
└─ ممنوع ❌
۳) اتصال متناوب (برگشت به عقب)?
└─ ممنوع ❌ (چون گراف باید DAG باشد)
۴) حداکثر یک منبع روی یک ورودی؟
└─ باشد ⇒ جایگزینی با پیام «اتصال قبلی جایگزین شد»
۵) شاخه شرطی بدون مقصد؟
└─ اجازه میشود، اما در «بررسی اعتبار» خطای هشداری میدهد
این پنل هیچ فرم کدنویسیشدهای ندارد. فرم کاملاً از schema همان گره
(بخش ۶ از Doc 02) ساخته میشود. این یعنی هر ماژول جدید، فرم جدید و بدون تغییر در کد فرانت.
┌───────────────────────────────────┐
│ ← ایجاد مخاطب [ بستن ]│ ← هدر: نام فارسی + اسلاگ
│ crm.contact.create │
│───────────────────────────────────│
│ ① ردیفهای اصلی فرم │
│ │
│ نام [________________] * │ ← required = ستاره قرمز
│ ایمیل[________________] 📋{{ }} │ ← دکمه انتخاب متغیر
│ وضعیت[ بکس لیست ▾ ] │ ← options از سرور
│ │
│───────────────────────────────────│
│ ▾ بخش پیشرفته (۴) │ ← جمعشده بهصورت پیشفرض
│ رفتار تکراری [ در صورت تکرار ]│
│ رشته خطا [ ] │
│───────────────────────────────────│
│ 📖 مستندات این گره · 🐞 آزمایش │ ← لینکهای کمکی
│───────────────────────────────────│
│ [ذخیره] [آزمایش گره] │ ← پایینچسب
└───────────────────────────────────┘
| نوع فیلد | کنترل UI | رفتار ویژه |
|---|---|---|
text | Input تکخطی | پشتیبانی از درج متغیر با {{ }} |
textarea | Input چندخطی | با شمارش کاراکتر + دکمه «درج متغیر» |
email / url | Input با اعتبارسنجی زنده | پیام خطا در لحظه تایپ (پس از blur) |
number / currency | Input عددی با فرمتبندی | فرمتبندی جداکننده هزارگان + واحد |
date / datetime | تقویم شمسی | انتخاب با منطقه زمانی + گزینه «نسبی» (3 days) |
select | Dropdown | گزینهها از options_source (endpoint سرور) + جستوجو اگر > ۱۵ گزینه |
multiselect | چندانتخابی + برچسب | امکان ایجاد گزینه جدید در صورت allow_new |
key_value | جدول دو ستونه | افزودن/حذف سطر + امکان درج متغیر در هر سلول |
expression | ادیتور Monaco (خطا) | قالببندی خودکار، کشف خطا در لحظه |
user_picker | جستوجوی زنده | debounce + ایندکس کیبورد (↑↓ Enter) |
contact_picker | جستوجوی زنده | نمایش نام + ایمیل + وضعیت در نتیجه |
در لحظه تایپ/blur. فوراً رنگ فیلد را عوض میکند و پیام کوتاه میدهد. هرگز جلوی «ذخیره» را نمیگیرد.
یک بار با schema کامل سرور. اگر خطا بود، به اولین فیلد خطا اسکرول میکند.
اعتبارسنجی کامل گراف: گره بدون محرک، شاخه بیمقصد، متغیر ناموجود. انتشار تا رفع مشکل مسدود است.
این کوچکترین اما سختترین بخش کل Builder است. اگر کاربر نتواند «نتیجه گره قبلی» را در یک فیلد قرار دهد، کل ارزش اتوماسیون از بین میرود.
کنار هر فیلد supports_variables. مودال باز میشود ← لیست گرههای قبل ← فیلدهای آنها.
پیشفرض: سادهترین و بصریترین روش
تایپ {{ درون فیلد ⇒ popup خودکار با لیست گرههای قبل.
برای: کاربران با تجربهتر
درگِ یک «فیلد خروجی» از پنل راست به داخل فیلد مقصد.
برای: وایرفریم مدرن؛ فاز ۲
┌──────────────────────────────────────────────────┐ │ انتخاب متغیر 🔍 جستوجو... │ │──────────────────────────────────────────────────│ │ ▾ Trigger — لیدفرم │ │ email │ maryam@acme.ir [درج] │ │ full_name │ مریم احمدی [درج] │ │ utm_source │ instagram [درج] │ │ ▾ گره ۱ — ایجاد مخاطب │ │ contact.id │ ctc_01J8X... [درج] │ │ contact.status│ new [درج] │ │ ▾ گره ۲ — ارسال پیامک │ │ status │ sent [درج] │ │ ▾ Environment │ │ tenant.name │ آکادمی رشد [درج] │ │──────────────────────────────────────────────────│ │ 💡 فقط متغیرهای گرههای «قبل این نقطه» نمایش │ │ داده میشوند — ترتیب بر اساس وابستگی گراف │ └──────────────────────────────────────────────────┘
| گزینه | مزیت | عیب | حکم |
|---|---|---|---|
| نمایش همه متغیرها | ساده در پیادهسازی | متغیرهایی نمایش داده میشوند که هنوز مقدار ندارند ⇒ خطا در اجرا | رد شد |
| فقط متغیرهای گرههای آنیسستر (مسیر قبل) | ۱۰۰٪ تضمین وجود مقدار؛ خطا حذف میشود | نیاز به محاسبه آنیسستر با هر تغییر گراف | انتخابشده |
| هر دو + علامت «هنوز مقدار ندارد» | انعطاف بیشتر | ارتباط بصری خروجی اجرا کاهش مییابد | فاز ۴ |
پس از ساخت، کاربر باید «ببیند چه اتفاقی میافتد». این مهمترین بخش از نظر اعتمادسازی است.
۱) کلیک «آزمایش» در نوار پایین
│
▼
۲) مودال «ورودی آزمایشی»:
├─ (الف) استفاده از آخرین وبهوک دریافتی (ذخیرهشده)
├─ (ب) قالب JSON خالی
├─ (ج) بارگذاری Sample Payload پیشنهادی
└─ (د) «اجرای گامبهگام» (Step-by-step)
│
▼
۳) شروع اجرا — نوار پیشرفت روی کانواس
· گره در حال اجرا: حاشیه آبی + پالس
· گره انجامشده: ● سبز + نمایش زمان (ms)
· گره شکستخورده: ✖ قرمز + پیام
· گره ردشده (branch): طوسی + «Missed»
│
▼
۴) پنل نتیجه (جایگزین پنل پیکربندی)
├─ جمعبندی: موفق/ناموفق + مدت کل
├─ هر گره: [ورودی] [خروجی] [خطا] با JSON مرتب
├─ دکمه «اجرای مجدد با همین ورودی»
├─ دکمه «ذخیره بهعنوان Test Case»
└─ دکمه «رفتن به اجراهای واقعی»
│
▼
۵) در حالت «گامبهگام» ⇒ با دکمه «قدم بعدی» هر گره
جدا اجرا میشود و خروجی قبلی درون متن بعدی درج میشود
گرههای عملیاتی (ارسال پیام، پرداخت، حذف) در حالت آزمایش فقط آنچه را که میفرستادند بهصورت Mock ثبت میکنند و خروجی موفق ساختگی برمیگردانند.
گرههای خواندنی (GET) اجرای واقعی دارند تا دادههای واقعی برای نمایش موجود باشد.
خطا باید بهمکان (گره خاص)، بهزمان (کدام تلاش) و با راهحل نمایش داده شود. خطای بیمکان و بدون راهحل، کاربر را از محصول فراری میدهد.
| سطح | کجا نمایش داده میشود | مثال | اکشن پیشنهادی |
|---|---|---|---|
| ۱) خطای فیلد | زیر همان فیلد + رنگ قرمز | «موبایل نامعتبر است» | هیچ — کاربر خودش اصلاح میکند |
| ۲) خطای گره | روی خود گره + بنر نوار پایین | «توکن API سرویس بیرونی نامعتبر است» | دکمه «باز کردن پیکربندی این گره» |
| ۳) خطای گراف | لیست در پنل «بررسی اعتبار» + علامت روی گره | «شاخه FALSE بدون مقصد است» | اسکرول و هایلایت گره مقصد |
| ۴) خطای سیستمی | Toast یا Modal سراسری | «ارتباط با سرور قطع شد» | دکمه «تلاش مجدد» + شمارش معکوس |
┌──────────────────────────────┐
│ ● HTTP Request ⚠ │ ← بج قرمز گوشه بالا
│──────────────────────────────│
│ ارسال به CRM │
│ ⛔ 401 Unauthorized │ ← کد خطای ماشینخوان
│ ⚠ توکن منقضی است │ ← خطای انسانی (فارسی)
│──────────────────────────────│
│ 🔄 تلاش ۲ از ۳ · ۱۲ ثانیه بعد│ ← وضعیت retry
└──────────────────────────────┘
│ کلیک
▼
┌──────────────────────────────┐
│ پنل خطا (Overlay): │
│ · زمان دقیق وقوع │
│ · کد HTTP + Response کامل │
│ · Payload ارسالی (mask شده) │
│ · خلاصه خطای بکاند │
│ │
│ [ویرایش توکن] [تلاش مجدد] │
│ [دیدن مستندات] │
└──────────────────────────────┘
گره شکست میخورد
│
├─ آیا قابل تکرار است؟ (timeout / 5xx / 429)
│ ├─ بله ⇒ زمانبندی تکرار با backoff نمایی
│ │ نمایش «تلاش ۲ از ۳» روی گره
│ └─ خیر ⇒ خطای نهایی + متوقف شدن مسیر
│
├─ آیا شاخه خطای (error branch) دارد؟
│ └─ بله ⇒ هدایت خطا به آن شاخه + علامت زرد
│
└─ آیا «ادامه در صورت خطا» فعال است؟
└─ بله ⇒ ثبت خطا + ادامه مسیر بعدی
با علامت زرد به جای قرمز
draft (پیشنویس) — فقط برای سازنده، اجرای واقعی نداردactive (فعال) — در حال اجرای واقعی استpaused (متوقف) — در صف اجرا نمیرودarchived (بایگانی) — فقط خواندنی، غیرقابل ویرایش [ذخیره (Save)] [انتشار (Publish)]
│ │
▼ ▼
ثبت پیشنویس فعلی اعتبارسنجی کامل گراف
قابل ویرایش در زمان بعدی ساخت snapshot در workflow_versions
اجرای واقعی تغییر نمیکند افزایش version + ثبت published_at
اجرای واقعی از این لحظه ← نسخه جدید
نسخه قبلی دستنخورده باقی میماند
══════════════════════════════════════════════════════
خروج از صفحه با تغییرات ذخیرهنشده:
«تغییرات ذخیرهنشده دارید. بدون ذخیره خارج میشوید؟»
کاربر پرکاربرد با کیبورد ۳ برابر موس سریع است. همه شورتکاتها در راهنمای شناور (?) و هنگام اولین ورود معرفی میشوند.
| کلید | عمل | حالت فعال |
|---|---|---|
| Ctrl/Cmd + S | ذخیره فوری | همیشه |
| Ctrl/Cmd + Z | Undo (برگرداندن) | همیشه |
| Ctrl/Cmd + Shift + Z | Redo | همیشه |
| Ctrl/Cmd + K | Command Palette (جستوجوی سراسری) | همیشه |
| P | باز / بستن پالت گرهها | وقتی هیچ فیلدی فوکوس نیست |
| Esc | لغو انتخاب / بستن پنل / بستن مودال | اولویت: مودال، بعد پنل |
| Delete / Backspace | حذف مورد انتخابشده | فقط با انتخاب فعال |
| Ctrl + A | انتخاب همه گرهها | کانواس |
| Ctrl + D | تکثیر گره انتخابشده | کانواس |
| Tab / Shift + Tab | رفتن به گره بعدی / قبلی در مسیر گراف | کانواس |
| Enter | باز کردن پیکربندی گره انتخابشده | کانواس |
| F | Fit to screen (نمایش کل گراف) | کانواس |
| 1 / 0 | زوم ۱۰۰٪ / زوم بیشینه | کانواس |
| T | اجرای آزمایشی | کانواس |
| ? | نمایش فهرست کامل شورتکاتها | همیشه |
پیام: «هنوز جریانی نساختهاید» + سه دکمه:
یک گره خاکستری «شروع کنید» در مرکز + دکمه + افزودن محرک. با کلیک، پالت باز و محرکها هایلایت میشوند.
| وضعیت | نمایش | رفتار |
|---|---|---|
| قطع شدن لحظهای | بنر نارنجی بالای صفحه «اتصال قطع شد — تغییرات محلی ذخیره میشوند» | صفبندی تغییرات در localStorage |
| وصل شدن مجدد | بنر سبز «همگامسازی...» سپس «بهروز شد» | اعمال صف به ترتیب + بررسی تداخل نسخه |
| تداخل (نسخه تغییر کرده) | مودال: «نسخه شما با سرور متفاوت است» | گزینه: نگهداشتن نسخه من / گرفتن از سرور / ادغام دستی |
Builder یک ابزار دسکتاپ است، اما باید در تبلت هم کار کند. موبایل فقط خواندنی است.
| عرض صفحه | حالت | رفتار |
|---|---|---|
| ≥ ۱۲۸۰px | دسکتاپ کامل | هر دو پنل + کانواس کامل، همه ابزارها |
| ۹۶۸ تا ۱۲۷۹px | تبلت / لپتاپ کوچک | پالت یا پنل: فقط یکی باز (پیشفرض پنل)؛ minimap حذف میشود |
| < ۹۶۸px | تبلت کوچک / موبایل | فقط «نمای خواندنی گراف» + لیست جریانها + اجرای واقعی؛ پیام «برای ویرایش از دسکتاپ استفاده کنید» |
aria-live="polite" اعلام میشوندprefers-reduced-motion: انیمیشن پالس/نبض حذف میشودفهرست کامل کامپوننتهای Vue مورد نیاز Builder با مسئولیت هرکدام. این فهرست مبنای تخمین توسعه است.
| نام کامپوننت | مسیر پیشنهادی | مسئولیت |
|---|---|---|
FlowCanvas.vue | builder/ | کانتینر اصلی Vue Flow: pan/zoom/minimap + مدیریت viewport |
BaseNode.vue | builder/nodes/ | قالب پایه همه گرهها: هدر، عنوان، خلاصه، نشان خطا، handles |
TriggerNode.vue | builder/nodes/ | گره محرک با رنگ سبز + نمایش نوع محرک |
ActionNode.vue | builder/nodes/ | گره اقدام با رنگ آبی + خلاصه پارامترهای کلیدی |
ConditionNode.vue | builder/nodes/ | گره شرط با دو خروجی TRUE/FALSE + آیکون دوشاخه |
CustomEdge.vue | builder/ | سیم سفارشی: رنگ شاخه، برچسب، دکمه حذف شناور |
CanvasGrid.vue | builder/ | شبکه نقطهچین + خطوط راهنمای تراز |
StartPlaceholder.vue | builder/ | گره خاکستری «شروع کنید» در کانواس خالی |
RunProgress.vue | builder/ | انیمیشن گره در حال اجرا + نوار پیشرفت کلی |
| نام کامپوننت | مسیر پیشنهادی | مسئولیت |
|---|---|---|
NodePalette.vue | builder/ | ستون چپ: جستوجو، دستهبندی، درگ منبع |
NodeCard.vue | builder/ | کارت یک گره در پالت: آیکون، نام، توضیح، بج ماژول |
NodeSearch.vue | builder/ | ورودی جستوجو با debounce و هایلایت نتیجه |
ConfigPanel.vue | builder/ | پنل راست: هدر گره + فرم پویا + فوتر دکمهها |
DynamicForm.vue | builder/form/ | رندر فرم از روی schema گره (قلب سیستم) |
FieldText.vue | builder/form/fields/ | فیلد متنی با دکمه درج متغیر |
FieldTextArea.vue | builder/form/fields/ | متن چندخطی + شمارنده + درج متغیر |
FieldSelect.vue | builder/form/fields/ | کشویی با گزینه ثابت یا options_source |
FieldMultiSelect.vue | builder/form/fields/ | چندانتخابی با برچسب + ایجاد گزینه جدید |
FieldKeyValue.vue | builder/form/fields/ | جدول دو ستونه پویا برای فیلدهای سفارشی |
FieldExpression.vue | builder/form/fields/ | ادیتور Monaco برای شرط و JSON |
FieldUserPicker.vue | builder/form/fields/ | جستوجوی زنده کاربر / مخاطب |
FieldDate.vue | builder/form/fields/ | تقویم شمسی + حالت تاریخ نسبی |
| نام کامپوننت | مسیر پیشنهادی | مسئولیت |
|---|---|---|
VariableButton.vue | builder/ | دکمه {{ }} کنار هر فیلد مجاز |
VariableModal.vue | builder/ | مودال لیست گرههای قبل + فیلدهای خروجی + دکمه درج |
TestRunModal.vue | builder/ | انتخاب ورودی آزمایشی: آخرین وبهوک / JSON / نمونه / گامبهگام |
TestResultPanel.vue | builder/ | نتیجه آزمایش: جمعبندی + هر گره [ورودی/خروجی/خطا] |
NodeErrorBadge.vue | builder/ | بج قرمز روی گره + جزئیات شناور با اکشن |
ValidatePanel.vue | builder/ | لیست خطاهای گراف پیش از انتشار با لینک پرش به گره |
VersionList.vue | builder/ | لیست نسخهها + دکمه بازگردانی |
TopBar.vue | builder/ | نوار بالا: نام، وضعیت، undo/redo، ذخیره، انتشار |
StatusBar.vue | builder/ | نوار پایین: ذخیره، تعداد گره، آخرین اجرا، دکمه آزمایش |
CommandPalette.vue | builder/ | جستوجوی سراسری ⌘K: گرهها + اکشنها + پرش سریع |
ShortcutHelp.vue | builder/ | مودال راهنمای همه شورتکاتها (?) |
ConflictModal.vue | builder/ | حل تداخل ویرایش همزمان چند کاربر |
UpgradePrompt.vue | builder/ | مودال «این گره به پلن/ماژول دیگری نیاز دارد» |
DynamicForm + سه فیلد پرکاربرد
(text، select، textarea) در اسپرینت اول فرانت.
// stores/workflow/builder.ts — قلب وضعیت Builder interface BuilderState { meta: WorkflowMeta; // نام، وضعیت، نسخه nodes: BuilderNode[]; // گرههای روی کانواس edges: BuilderEdge[]; // سیمها selection: string[]; // گرههای انتخابشده history: HistoryStack; // Undo/Redo (حداکثر ۵۰ قدم) dirty: boolean; // تغییرات ذخیرهنشده saving: boolean; // در حال ذخیره runState: RunState | null; // وضعیت اجرای آزمایشی } interface BuilderActions { addNode(type: string, pos: XY): BuilderNode; removeNode(id: string): void; connect(src: HandleRef, dst: HandleRef): BuilderEdge | null; updateNodeConfig(id: string, patch: ConfigPatch): void; validate(): ValidationIssue[]; testRun(payload: TestPayload): Promise<TestResult>; publish(): Promise<VersionInfo>; }
Vue Flow (view) ◄──► Pinia Store (state)
│ │
│ drag / connect │ debounced autosave (2s)
▼ ▼
Layout cache (pos) API Client (useWorkflowApi)
│
┌──────────┴──────────┐
▼ ▼
POST /draft POST /validate
(ذخیره پیشنویس) (بررسی اعتبار)
قوانین:
✦ Store هرگز مستقیم به API وصل نیست؛ فقط از طریق composable
✦ تاریخچه Undo فقط در حافظه است (بین رفرشها باقی نمیماند)
✦ هر تغییر → dirty=true → autosave فعال میشود
| موضوع | تصمیم | دلیل |
|---|---|---|
| کتابخانه گراف | @vue-flow/core + @vue-flow/background + @vue-flow/minimap | بومی Vue، باندل کوچک، API پایدار |
| مدل رندر گره | کامپوننت Vue سفارشی بهازای هر kind | انعطاف کامل در طراحی و حالتها |
| زوم/پن | بومی Vue Flow با محدوده ۰.۲۵ تا ۲ | عملکرد GPU-accelerated |
| پایداری موقعیت | ذخیره x/y در workflow_nodes.position | سرور منبع حقیقت چیدمان است |
| آفلاین | localStorage + صف همگامسازی | کاربر نباید کارش را از دست بدهد |
| ادیتور عبارت | @monaco-editor/loader (lazy load) | حجم بزرگ — فقط وقتی لازم است لود شود |
| شاخص | تعریف | هدف فاز ۱ | ابزار سنجش |
|---|---|---|---|
| Time-to-First-Flow | زمان از ورود به Builder تا اولین اجرای موفق | < ۵ دقیقه برای قالب آماده | Telemetry رویدادها |
| Node discovery time | زمان پیداکردن گره درست در پالت | < ۱۰ ثانیه (متوسط) | تست کاربردپذیری |
| Config completion rate | ٪ گرههایی که بدون خطا پیکربندی میشوند | > ۸۵٪ | Validation events |
| Publish success rate | ٪ انتشار موفق در تلاش اول | > ۷۰٪ | لاگ انتشار |
| Test run coverage | ٪ جریانهایی که حداقل یکبار تست شدهاند | > ۹۰٪ | رویدادهای اجرا |
| Support tickets / flow | تیکت پشتیبانی بهازای هر ۱۰۰ جریان فعال | < ۵ | سیستم تیکت |
«وقتی مخاطب جدید ساخته شد، یک پیامک خوشآمد بفرست و تسک پیگیری بساز.»
موفقیت: اجرای آزمایشی موفق بدون کمک
«اگر امتیاز ≥ ۶۰ بود، به تیم فروش تخصیص بده؛ وگرنه برچسب پرورش بزن.»
موفقیت: ساخت شرط + دو شاخه درست
«این جریان خطا دارد؛ پیداش کن و درستش کن.» (شاخه بیمقصد، متغیر ناموجود)
موفقیت: پیدا کردن خطا با راهنمایی پنل، بدون تماس با پشتیبانی
«تغییرات امروز را برگردان به نسخه دیروز.»
موفقیت: استفاده درست از VersionList
پیادهسازی Builder در ۶ اسپرینت دوهفتهای موازی با توسعه بکاند (تیم فرانت ۱ نفر).
FlowCanvas با زوم/پن/minimapBaseNode + سه نوع گره (Trigger/Action/Condition)TopBar + StatusBar + چیدمان ۵ ناحیهNodePalette + جستوجو + کشیدن روی کانواسDynamicForm + فیلدهای text/select/textareaschema از GET /nodes/typesVariableModal با منطق «فقط گرههای قبل»TestRunModal + TestResultPanelRunProgress)ValidatePanel + NodeErrorBadgeVersionList + بازگردانیCommandPaletteپالت · نوار بالا · کانواس · پنل پیکربندی · نوار وضعیت
۹ کانواس · ۱۳ فرم و پالت · ۱۳ متغیر/تست/پیام
ذخیره · undo · پالت · تست · راهنما
از Time-to-First-Flow تا تیکت پشتیبانی
فیلد · گره · گراف · سیستمی
متن · انتخابی · چندخطی (اول توسعه)
~۳ ماه با یک توسعهدهنده فرانت
فرم هرگز کدنویسی نمیشود؛ از schema ساخته میشود