سند طراحی محصول — Doc 04

طراحی ورک‌فلو بیلدر
UX Design & Component Inventory

جامع‌ترین سند تجربه کاربری Workflow Builder: چیدمان کانواس، سیم‌کشی، پالت گره‌ها، پنل پیکربندی پویا، انتخاب متغیر، اجرای آزمایشی، نمایش خطا، کیبورد شورتکات‌ها، فهرست کامل کامپوننت‌ها، معماری فنی در Nuxt و معیارهای سنجش موفقیت.

کاربرد: پنل مشتری + پنل Super Admin لایه نمایش: Nuxt 4 + Vue 3 گراف: @vue-flow/core متریک: Time-to-First-Flow < ۵ دقیقه مکمل: Doc 01 + 02 + 03

۱ اصول راهنمای UX

کل طراحی Builder تحت تأثیر یک واقعیت قرار دارد: کاربر این محصول، برنامه‌نویس نیست. مدیر فروش، بازاریاب یا صاحب کسب‌وکار باید بدون آموزش بتواند جریان بسازد. پس «سادگی» اولویت اول است و «امکانات» دوم.

۱) سادگی، سپس قدرت

پیش‌فرض ساده؛ گزینه‌های پیشرفته در accordion پنهان. ۸۰٪ کاربران هرگز آن‌ها را نخواهند دید.

۲) بدون لحظه سفید

صفحه هرگز خالی و بی‌معنا نیست. همیشه یک نقطه شروع، قالب آماده یا راهنمای روی صفحه هست.

۳) فوری (Feedback < ۱۰۰ms)

به هر کلیک، بکشید و رها کردن باید فوراً بازخورد بصری برسد؛ بدون این، احساس کندی می‌شود.

۴) خطای قابل بازیابی

هیچ خطایی غیرقابل ترمیم نیست. هر خطا پیام + راه‌حل + دکمه بازیابی مستقیم دارد.

۵) مبتنی بر شیء نیست، مبتنی بر هدف

برچسب «Action» ندهید؛ بگویید «ارسال پیامک به مشتری جدید». همه چیز با زبان کاربر توضیح داده می‌شود.

۶) قابل پیش‌بینی

کشیدن، رها کردن، بستن، ذخیره — همه رفتارها ثابت و یکسان در کل پنل هستند.

بزرگ‌ترین خطر UX: ساخت یک Builder که «هر کاری را» می‌تواند انجام دهد اما کاربر نمی‌فهمد «کجا باید شروع کند». راهکار این سند، محدود کردن مسیر اصلی به سه عمل (اتصال، پیکربندی، آزمایش) و تلاش برای پنهان کردن بقیه است.

۲ شخصیت‌های کاربری (Personas)

شخصیتنقشهدف اصلیبزرگ‌ترین ترستعداد مواجهه
فرهاد فروشندهکارشناس فروش پیگیری سریع لیدهای گرم بدون گم شدن زیاده‌روی در فرم‌ها و تنظیمات پیچیده روزانه (بسیار بالا)
مریم مدیر بازاریابیبازاریاب ساخت کمپین و اتوماسیون ایمیلی بدون کمک تیم فنی «نمی‌دونم متغیر کجا قرار بگیره» هفتگی
سامان مدیرعاملمدیر داشبورد + دیدن اینکه چه چیزی خودکار انجام می‌شود شلوغی و نبود جمع‌بندی ساده ماهانه
نوید توسعه‌دهنده مشتریفنی / API اتصال سیستم داخلی از طریق Webhook و HTTP نبود مستندات و محدودیت بیش از حد فقط هنگام راه‌اندازی
ارشاد پشتیبانیتیم ما پیدا کردن سریع دلیل شکست یک جریان نبود لاگ و ابزار دیباگ روزانه
چه کسی پیش‌فرض طراحی است؟ «مریم» و «فرهاد». اگر طرحی بین فرایند آنها و نیاز «نوید» تعارض پیدا کرد، اولویت با فردهای غیرفنی است. نوید همیشه می‌تواند از API استفاده کند ولی مریم راه‌حل دیگری ندارد.

۳ چیدمان کلی صفحه Builder

صفحه 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 فضا داشته باشد.

۴ کانواس و رفتار آن

۴.۱ ناحیه‌های داخلی یک گره (Node Anatomy)

┌─────────────────────────────────┐
│ ●  ① آیکون نوع   [جداشده] ②    │ ← هدر رنگی، برچسب نوع
│─────────────────────────────────│
│  ③ عنوان کاربری                │ ← «ارسال پیامک» (قابل ویرایش دوبار کلیک)
│  ④ خلاصه مقدارها               │ ← «به ۰۹۱۲… · قالب: خوش‌آمد»
│─────────────────────────────────│
│  ⚠ ⑤ نشان خطا (در صورت وجود)  │
└─────────────────────────────────┘
      ⑥ ورودی (چپ)              ⑦ خروجی (راست)
         ◯ ........................◯
              ⑧ دسته اتصال: دایره‌ای همیشه در لبه، هیچ‌وقت وسط گره
رفتارعملکردبازخورد
کلیکانتخاب گره + باز شدن پنل پیکربندیحاصل‌شدن حاشیه ۲px آبی
کلیک دوبارهویرایش مستقیم عنوان گرهتبدیل به Input با حاشیه فعال
درگ (کشیدن)جابه‌جایی گره — Snap به شبکه ۸pxسایه روشن هنگام هل دادن + نمایش X/Y
Shift + درگجابه‌جایی آزاد بدون Snapخط‌چاک عمودی راهنما
کلیک دوبار روی لبه پایینافزودن سریع گره جدید بعدی (کوتاه‌ترین مسیر)نمایش مودال کوچک انتخاب گره
Ctrl/Cmd + کلیکانتخاب چندگانه گره‌هاشمای چندگانه با حاشیه نقطه‌چین
Delحذف گره (با تأیید اگر فعال باشد)Toast با دکمه Undo ۵ ثانیه‌ای

۴.۲ رفتار کانواس

پیمایش

  • اسکرول موس = زوم (تا ۲۵٪ تا ۲۰۰٪)
  • دکمه وسط + درگ = Pan
  • دکمه راست در خالی = منوی زمینه
  • دکمه Fit = نمایش کل گراف

چیدمان خودکار

  • دکمه Auto-Layout → مرتب‌سازی سلسله‌مراتبی چپ به راست
  • الفبایی نیست؛ بر اساس شاخه منطقی
  • پیش‌نمایش قبل از اعمال
  • موقعیت قبلی در Undo history

راهنماها

  • شبکه نقطه‌چین ملایم (Grid)
  • Snapping به همسایه‌ها در عرض ۱۲px
  • نمایش فاصله واریانت (Alignment guides)
  • Minimap در گوشه چپ پایین

۵ پالت گره‌ها (Node Palette)

پالت، ویترین کل گره‌هاست. اگر کاربر نتواند در ۱۰ ثانیه گره درست را پیدا کند، طراحی شکست خورده است.

┌────────────────────────────┐
│ 🔍 جست‌وجوی گره...       [⌘K]│
│────────────────────────────│
│ ✦ پیشنهادی برای شما        │   ← بر اساس گره‌های موجود
│   [ارسال ایمیل] [پیامک]    │
│────────────────────────────│
│ ▸ محرک‌ها            (۸)   │   ← جمع‌شده به‌صورت پیش‌فرض
│   ▸ CRM                   │
│   ▸ فرم وب                │
│   ▸ زمان‌بندی              │
│ ▾ اقدام‌ها            (۹)   │   ← باز
│     crm.contact.create      │   ← کارت با آیکون + نام فارسی
│     crm.contact.update      │
│     crm.deal.move_stage     │
│   ▸ HTTP و داده            │
│   ▸ پیام‌رسان             │
│ ▸ شرط‌ها              (۵)   │
│ ▸ پیکربندی جریان       (۳)   │
│────────────────────────────│
│ 💡 «گره مورد نیافتید؟»    │
│     درخواست گره جدید       │
└────────────────────────────┘
عنصررفتارتوضیح
جست‌وجوفیلتر زنده با debounce ۱۵۰msهم بر اساس اسلاگ انگلیسی، هم برچسب فارسی و توضیحات
کارتهای گرهدرگ + رها روی کانواسآیکون + نام فارسی + توضیح کوتاه یک‌خطی
گره‌های غیرفعالطوسی + بج «ماژول لازم»کلیک ⇒ مودال ارتقای پلن / نصب ماژول
تعداد دستهنمایش عددی پشت هر دستهبه کاربر نشان می‌دهد چه امکاناتی دارد
کلید ⌘KCommand Palette عمومیجست‌وجوی سراسری در همه گره‌ها + کارها
حالت «پیشنهادی»۳ گره پرکاربرد بالای پالتبر اساس وضعیت فعلی جریان محاسبه می‌شود
دسته‌بندی پیش‌فرض: محرک‌ها، اقدام‌ها، شرط‌ها، تبدیل داده، زمان‌بندی، ارتباطات (وابسته به ماژول). ترتیب دسته‌ها بر اساس فراوانی استفاده واقعی در سال اول بازبینی می‌شود.

۶ سیم‌کشی و گره‌های اتصال (Wiring)

۶.۱ رفتار اتصال

   (درگ از دسته خروجی)                  (هنگام رها کردن)
      ① ◯──┐                          ┌──◯ ② ◯──┐
            │  ② سیم متحرک با نوک      │  ④ خط خطا
            │     دنبال‌کننده         │    قرمز اگر نامعتبر
            ▼                          ▼
   [گره منبع]  ····◯(ghost)····►  [گره مقصد معتبر]
                                       ③ Snap به دسته ورودی با بزرگنمایی
مرحلهرفتاربازخورد بصری
۱) شروع درگ از دستهدسته بزرگ می‌شود + سیم شناور پدیدار می‌شوددسته: ۸px → ۱۴px + هاله
۲) حرکتسیم با خم منحنی Bezier به نوک موس دنبال می‌شوددسته‌های واجد شرایط نزدیک چشمک می‌زنند
۳) نزدیک شدنSnap خودکار به دسته ورودی معتبرحلقه نارنجی دور دسته مقصد
۴) رها کردن روی مقصد نامعتبراتصال انجام نمی‌شودلرزش خفیف + tooltip «اتصال مجاز نیست»
۵) رها کردن روی مقصد معتبرساخت یال + ذخیره خودکارانیمیشن نبض + Toast «اتصال ایجاد شد»
۶) حذف سیمکلیک وسط سیم + Del یا کلیک راستmenu: حذف / برعکس کردن

۶.۲ منطق «می‌توان متصل کرد؟» (Valid Connection)

  قواعد اعتبارسنجی هنگام سیم‌کشی:

  ۱) نوع خروجی سازگار با نوع ورودی؟
        ├─ همه → همه          ⇒ مجاز (پیش‌فرض)
        └─ شرط دارای خروجی‌های TRUE/FALSE  ⇒ مجاز فقط به گره بعدی

  ۲) اتصال خود-به-خود؟ (self-loop)
        └─ ممنوع ❌

  ۳) اتصال متناوب (برگشت به عقب)?
        └─ ممنوع ❌ (چون گراف باید DAG باشد)

  ۴) حداکثر یک منبع روی یک ورودی؟
        └─ باشد ⇒ جایگزینی با پیام «اتصال قبلی جایگزین شد»

  ۵) شاخه شرطی بدون مقصد؟
        └─ اجازه می‌شود، اما در «بررسی اعتبار» خطای هشداری می‌دهد
یک محدودیت حیاتی: اتصال نباید در حالت ویرایش سیم‌کشی تکراری ایجاد شود. اگر کاربر چند بار بکشد و رها کند، سیستم باید همه را «یک یال» در نظر بگیرد. همچنین حذف سیم نباید خالی کردن اجباری ایجاد کند؛ کاربر باید همیشه یک مسیر فعال داشته باشد.

۷ پنل پیکربندی پویا (Config Panel)

این پنل هیچ فرم کدنویسی‌شده‌ای ندارد. فرم کاملاً از schema همان گره (بخش ۶ از Doc 02) ساخته می‌شود. این یعنی هر ماژول جدید، فرم جدید و بدون تغییر در کد فرانت.

┌───────────────────────────────────┐
│  ← ایجاد مخاطب           [ بستن ]│   ← هدر: نام فارسی + اسلاگ
│  crm.contact.create               │
│───────────────────────────────────│
│  ① ردیف‌های اصلی فرم              │
│                                   │
│  نام [________________] *         │   ← required = ستاره قرمز
│  ایمیل[________________] 📋{{ }}  │   ← دکمه انتخاب متغیر
│  وضعیت[  بکس لیست  ▾ ]           │   ← options از سرور
│                                   │
│───────────────────────────────────│
│  ▾ بخش پیشرفته (۴)                │   ← جمع‌شده به‌صورت پیش‌فرض
│    رفتار تکراری [ در صورت تکرار ]│
│    رشته خطا   [ ]                │
│───────────────────────────────────│
│  📖 مستندات این گره  ·  🐞 آزمایش  │   ← لینک‌های کمکی
│───────────────────────────────────│
│         [ذخیره]   [آزمایش گره]     │   ← پایین‌چسب
└───────────────────────────────────┘

۷.۱ انواع فیلد و رفتار هرکدام

نوع فیلدکنترل UIرفتار ویژه
textInput تک‌خطیپشتیبانی از درج متغیر با {{ }}
textareaInput چندخطیبا شمارش کاراکتر + دکمه «درج متغیر»
email / urlInput با اعتبارسنجی زندهپیام خطا در لحظه تایپ (پس از blur)
number / currencyInput عددی با فرمت‌بندیفرمت‌بندی جداکننده هزارگان + واحد
date / datetimeتقویم شمسیانتخاب با منطقه زمانی + گزینه «نسبی» (3 days)
selectDropdownگزینه‌ها از options_source (endpoint سرور) + جست‌وجو اگر > ۱۵ گزینه
multiselectچندانتخابی + برچسبامکان ایجاد گزینه جدید در صورت allow_new
key_valueجدول دو ستونهافزودن/حذف سطر + امکان درج متغیر در هر سلول
expressionادیتور Monaco (خطا)قالب‌بندی خودکار، کشف خطا در لحظه
user_pickerجست‌وجوی زندهdebounce + ایندکس کیبورد (↑↓ Enter)
contact_pickerجست‌وجوی زندهنمایش نام + ایمیل + وضعیت در نتیجه

۷.۲ اعتبارسنجی سه‌لایه

لایه ۱ — لحظه‌ای (Client)

در لحظه تایپ/blur. فوراً رنگ فیلد را عوض می‌کند و پیام کوتاه می‌دهد. هرگز جلوی «ذخیره» را نمی‌گیرد.

لایه ۲ — هنگام ذخیره (Save)

یک بار با schema کامل سرور. اگر خطا بود، به اولین فیلد خطا اسکرول می‌کند.

لایه ۳ — پیش از انتشار (Publish)

اعتبارسنجی کامل گراف: گره بدون محرک، شاخه بی‌مقصد، متغیر ناموجود. انتشار تا رفع مشکل مسدود است.

قانون طلایی ذخیره: ذخیره پیش‌نویس هرگز توسط اعتبارسنجی مسدود نمی‌شود — فقط انتشار (Publish) مسدود می‌شود. کاربر باید بتواند کار نیمه‌تمام را رها کند و فردا ادامه دهد. خطاهای جدی فقط با بنر زرد در نوار پایین نمایش داده می‌شوند.

۸ انتخاب متغیر (Variable Picker)

این کوچک‌ترین اما سخت‌ترین بخش کل 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»
        └─ دکمه «رفتن به اجراهای واقعی»
         │
         ▼
  ۵) در حالت «گام‌به‌گام» ⇒ با دکمه «قدم بعدی» هر گره
     جدا اجرا می‌شود و خروجی قبلی درون متن بعدی درج می‌شود

تفاوت آزمایش و اجرای واقعی

  • آزمایش: محیط موقت، بدون شمارش مصرف، گره‌های عملیاتی Dry-Run (بدون ارسال واقعی)
  • واقعی: صف اجرای تولید، شمارش متریک، اثر واقعی (پیامک، رکورد، پرداخت)
  • نوار پایین همیشه بج «آزمایشی / واقعی» نشان می‌دهد

Dry-Run چیست؟

گره‌های عملیاتی (ارسال پیام، پرداخت، حذف) در حالت آزمایش فقط آنچه را که می‌فرستادند به‌صورت Mock ثبت می‌کنند و خروجی موفق ساختگی برمی‌گردانند.

گره‌های خواندنی (GET) اجرای واقعی دارند تا داده‌های واقعی برای نمایش موجود باشد.

چرا این بخش مهم‌ترین است؟ چون مشتری فقط با «دیدن نتیجه» باور می‌کند سیستم کار می‌کند. یک تست ناموفق که دلیل و راه‌حل را به‌وضوح نشان دهد، هزار بار بهتر از یک تست موفق بدون توضیح است.

۱۰ نمایش خطا و لبه‌ها (Error UX)

خطا باید به‌مکان (گره خاص)، به‌زمان (کدام تلاش) و با راه‌حل نمایش داده شود. خطای بی‌مکان و بدون راه‌حل، کاربر را از محصول فراری می‌دهد.

۱۰.۱ چهار سطح خطا

سطحکجا نمایش داده می‌شودمثالاکشن پیشنهادی
۱) خطای فیلد زیر همان فیلد + رنگ قرمز «موبایل نامعتبر است» هیچ — کاربر خودش اصلاح می‌کند
۲) خطای گره روی خود گره + بنر نوار پایین «توکن API سرویس بیرونی نامعتبر است» دکمه «باز کردن پیکربندی این گره»
۳) خطای گراف لیست در پنل «بررسی اعتبار» + علامت روی گره «شاخه FALSE بدون مقصد است» اسکرول و هایلایت گره مقصد
۴) خطای سیستمی Toast یا Modal سراسری «ارتباط با سرور قطع شد» دکمه «تلاش مجدد» + شمارش معکوس

۱۰.۲ آناتومی نمایش خطا روی یک گره

   ┌──────────────────────────────┐
   │ ● HTTP Request            ⚠  │  ← بج قرمز گوشه بالا
   │──────────────────────────────│
   │  ارسال به CRM                │
   │  ⛔ 401 Unauthorized          │  ← کد خطای ماشین‌خوان
   │  ⚠ توکن منقضی است            │  ← خطای انسانی (فارسی)
   │──────────────────────────────│
   │  🔄 تلاش ۲ از ۳ · ۱۲ ثانیه بعد│  ← وضعیت retry
   └──────────────────────────────┘
        │ کلیک
        ▼
   ┌──────────────────────────────┐
   │ پنل خطا (Overlay):           │
   │ · زمان دقیق وقوع             │
   │ · کد HTTP + Response کامل     │
   │ · Payload ارسالی (mask شده)   │
   │ · خلاصه خطای بک‌اند           │
   │                              │
   │ [ویرایش توکن] [تلاش مجدد]     │
   │ [دیدن مستندات]                │
   └──────────────────────────────┘

۱۰.۳ جریان تصمیم‌گیری خطا

  گره شکست می‌خورد
       │
       ├─ آیا قابل تکرار است؟ (timeout / 5xx / 429)
       │     ├─ بله ⇒ زمان‌بندی تکرار با backoff نمایی
       │     │        نمایش «تلاش ۲ از ۳» روی گره
       │     └─ خیر ⇒ خطای نهایی + متوقف شدن مسیر
       │
       ├─ آیا شاخه خطای (error branch) دارد؟
       │     └─ بله ⇒ هدایت خطا به آن شاخه + علامت زرد
       │
       └─ آیا «ادامه در صورت خطا» فعال است؟
             └─ بله ⇒ ثبت خطا + ادامه مسیر بعدی
                      با علامت زرد به جای قرمز
قاعده طلایی: هرگز نگویید «An unknown error occurred». سه چیز الزامی است: چه اتفاقی افتاد (فارسی)، کجا (گره + زمان)، و چه کاری باید بکند (دکمه عملیاتی). اگر سومی قابل نوشتن نیست، آن خطا باید به تیم پشتیبانی گزارش شود نه به کاربر.

۱۱ ذخیره، وضعیت و بازگشت نسخه

ذخیره خودکار (Autosave)

  • با debounce ۲ ثانیه‌ای پس از هر تغییر
  • نمایش «در حال ذخیره... / ذخیره شد ۲ ثانیه پیش» در نوار پایین
  • در صورت قطعی اینترنت: ذخیره محلی (localStorage) + همگام‌سازی پس از وصل شدن
  • ویرایش هم‌زمان چند کاربر: سیاست Last-write-wins + بنر هشدار تداخل

چهار وضعیت جریان

  • draft (پیش‌نویس) — فقط برای سازنده، اجرای واقعی ندارد
  • active (فعال) — در حال اجرای واقعی است
  • paused (متوقف) — در صف اجرا نمی‌رود
  • archived (بایگانی) — فقط خواندنی، غیرقابل ویرایش

۱۱.۱ تمایز حیاتی «ذخیره» و «انتشار»

  [ذخیره (Save)]                      [انتشار (Publish)]
       │                                      │
       ▼                                      ▼
  ثبت پیش‌نویس فعلی                     اعتبارسنجی کامل گراف
  قابل ویرایش در زمان بعدی              ساخت snapshot در workflow_versions
  اجرای واقعی تغییر نمی‌کند              افزایش version + ثبت published_at
                                        اجرای واقعی از این لحظه ← نسخه جدید
                                        نسخه قبلی دست‌نخورده باقی می‌ماند

  ══════════════════════════════════════════════════════
  خروج از صفحه با تغییرات ذخیره‌نشده:
  «تغییرات ذخیره‌نشده دارید. بدون ذخیره خارج می‌شوید؟»
بازگشت نسخه (Rollback): در منوی بالای صفحه، لیست نسخه‌های منتشرشده با تاریخ و نام منتشرکننده + دکمه «بازگردانی به این نسخه». بازگردانی همیشه نسخه جدید می‌سازد (نسخه‌ها هرگز overwrite نمی‌شوند) تا تاریخچه کامل حفظ شود.

۱۲ کیبورد شورتکات‌ها

کاربر پرکاربرد با کیبورد ۳ برابر موس سریع است. همه شورتکات‌ها در راهنمای شناور (?) و هنگام اولین ورود معرفی می‌شوند.

کلیدعملحالت فعال
Ctrl/Cmd + Sذخیره فوریهمیشه
Ctrl/Cmd + ZUndo (برگرداندن)همیشه
Ctrl/Cmd + Shift + ZRedoهمیشه
Ctrl/Cmd + KCommand Palette (جست‌وجوی سراسری)همیشه
Pباز / بستن پالت گره‌هاوقتی هیچ فیلدی فوکوس نیست
Escلغو انتخاب / بستن پنل / بستن مودالاولویت: مودال، بعد پنل
Delete / Backspaceحذف مورد انتخاب‌شدهفقط با انتخاب فعال
Ctrl + Aانتخاب همه گره‌هاکانواس
Ctrl + Dتکثیر گره انتخاب‌شدهکانواس
Tab / Shift + Tabرفتن به گره بعدی / قبلی در مسیر گرافکانواس
Enterباز کردن پیکربندی گره انتخاب‌شدهکانواس
FFit to screen (نمایش کل گراف)کانواس
1 / 0زوم ۱۰۰٪ / زوم بیشینهکانواس
Tاجرای آزمایشیکانواس
?نمایش فهرست کامل شورتکات‌هاهمیشه
قانون ایمنی شورتکات: هیچ کلید تکی (بدون Ctrl) مجاز به انجام کار مخرب (حذف، خروج) نیست. همه کلیدهای تکی فقط وقتی فعالند که هیچ Input فیلدی فوکوس نباشد تا از اجرای تصادفی هنگام تایپ جلوگیری شود.

۱۳ حالت‌های خالی و بارگذاری (Empty / Loading)

صفحه «جریان‌ها» خالی

پیام: «هنوز جریانی نساخته‌اید» + سه دکمه:

  • شروع با قالب (پیشنهاد اول)
  • ساخت از صفر
  • تماشای آموزش ۲ دقیقه‌ای

کانواس خالی (نود شروع)

یک گره خاکستری «شروع کنید» در مرکز + دکمه + افزودن محرک. با کلیک، پالت باز و محرک‌ها هایلایت می‌شوند.

در حال بارگذاری

  • Skeleton شکل گره‌ها (نه اسپینر خالی)
  • Timeout بیش از ۸ ثانیه ⇒ پیام + دکمه تلاش مجدد
  • هرگز صفحه کاملاً سفید نمی‌ماند

۱۳.۱ حالت‌های ارتباطی (Offline / Reconnect)

وضعیتنمایشرفتار
قطع شدن لحظه‌ایبنر نارنجی بالای صفحه «اتصال قطع شد — تغییرات محلی ذخیره می‌شوند»صف‌بندی تغییرات در localStorage
وصل شدن مجددبنر سبز «همگام‌سازی...» سپس «به‌روز شد»اعمال صف به ترتیب + بررسی تداخل نسخه
تداخل (نسخه تغییر کرده)مودال: «نسخه شما با سرور متفاوت است»گزینه: نگه‌داشتن نسخه من / گرفتن از سرور / ادغام دستی

۱۴ واکنش‌گرایی (Responsive)

Builder یک ابزار دسکتاپ است، اما باید در تبلت هم کار کند. موبایل فقط خواندنی است.

عرض صفحهحالترفتار
≥ ۱۲۸۰pxدسکتاپ کاملهر دو پنل + کانواس کامل، همه ابزارها
۹۶۸ تا ۱۲۷۹pxتبلت / لپ‌تاپ کوچکپالت یا پنل: فقط یکی باز (پیش‌فرض پنل)؛ minimap حذف می‌شود
< ۹۶۸pxتبلت کوچک / موبایلفقط «نمای خواندنی گراف» + لیست جریان‌ها + اجرای واقعی؛ پیام «برای ویرایش از دسکتاپ استفاده کنید»
قانون تاچ: همه دسته‌ها و دکمه‌های عملیاتی حداقل ۴۴×۴۴px هستند. درگ با انگشت فقط در «حالت لمسی» فعال می‌شود (تأخیر ۱۵۰ms برای جلوگیری از اسکرول تصادفی).

۱۵ دسترسی‌پذیری (Accessibility)

کیبورد-محور

  • همه عملیات با کیبورد قابل انجام است (بخش ۱۲)
  • ترتیب Tab منطقی: نوار بالا → پالت → کانواس → پنل → نوار پایین
  • فوکوس همیشه قابل مشاهده (حلقه آبی ۲px)

خوانش‌گر صفحه (Screen Reader)

  • هر گره یک برچسب ARIA: «گره اقدام — ارسال پیامک — وضعیت: پیکربندی شده»
  • تغییرات وضعیت با aria-live="polite" اعلام می‌شوند
  • جایگزین متنی برای کانواس: «لیست گره‌ها» در نمای جدولی

کنتراست و رنگ

  • رنگ به‌تنهایی معنای وضعیت را منتقل نمی‌کند — همیشه آیکون + متن همراه است
  • حالت «کنتراست بالا» در تنظیمات کاربری
  • فاقد وابستگی به توانایی تشخیص قرمز/سبز

کاهش حرکت

  • احترام به prefers-reduced-motion: انیمیشن پالس/نبض حذف می‌شود
  • انتقال‌ها حداکثر ۱۵۰ms

۱۶ فهرست کامپوننت‌ها (Component Inventory)

فهرست کامل کامپوننت‌های Vue مورد نیاز Builder با مسئولیت هرکدام. این فهرست مبنای تخمین توسعه است.

۱۶.۱ کامپوننت‌های کانواس و گراف

نام کامپوننتمسیر پیشنهادیمسئولیت
FlowCanvas.vuebuilder/کانتینر اصلی Vue Flow: pan/zoom/minimap + مدیریت viewport
BaseNode.vuebuilder/nodes/قالب پایه همه گره‌ها: هدر، عنوان، خلاصه، نشان خطا، handles
TriggerNode.vuebuilder/nodes/گره محرک با رنگ سبز + نمایش نوع محرک
ActionNode.vuebuilder/nodes/گره اقدام با رنگ آبی + خلاصه پارامترهای کلیدی
ConditionNode.vuebuilder/nodes/گره شرط با دو خروجی TRUE/FALSE + آیکون دوشاخه
CustomEdge.vuebuilder/سیم سفارشی: رنگ شاخه، برچسب، دکمه حذف شناور
CanvasGrid.vuebuilder/شبکه نقطه‌چین + خطوط راهنمای تراز
StartPlaceholder.vuebuilder/گره خاکستری «شروع کنید» در کانواس خالی
RunProgress.vuebuilder/انیمیشن گره در حال اجرا + نوار پیشرفت کلی

۱۶.۲ کامپوننت‌های پالت و پیکربندی

نام کامپوننتمسیر پیشنهادیمسئولیت
NodePalette.vuebuilder/ستون چپ: جست‌وجو، دسته‌بندی، درگ منبع
NodeCard.vuebuilder/کارت یک گره در پالت: آیکون، نام، توضیح، بج ماژول
NodeSearch.vuebuilder/ورودی جست‌وجو با debounce و هایلایت نتیجه
ConfigPanel.vuebuilder/پنل راست: هدر گره + فرم پویا + فوتر دکمه‌ها
DynamicForm.vuebuilder/form/رندر فرم از روی schema گره (قلب سیستم)
FieldText.vuebuilder/form/fields/فیلد متنی با دکمه درج متغیر
FieldTextArea.vuebuilder/form/fields/متن چندخطی + شمارنده + درج متغیر
FieldSelect.vuebuilder/form/fields/کشویی با گزینه ثابت یا options_source
FieldMultiSelect.vuebuilder/form/fields/چندانتخابی با برچسب + ایجاد گزینه جدید
FieldKeyValue.vuebuilder/form/fields/جدول دو ستونه پویا برای فیلدهای سفارشی
FieldExpression.vuebuilder/form/fields/ادیتور Monaco برای شرط و JSON
FieldUserPicker.vuebuilder/form/fields/جست‌وجوی زنده کاربر / مخاطب
FieldDate.vuebuilder/form/fields/تقویم شمسی + حالت تاریخ نسبی

۱۶.۳ کامپوننت‌های متغیر، آزمایش و پیام

نام کامپوننتمسیر پیشنهادیمسئولیت
VariableButton.vuebuilder/دکمه {{ }} کنار هر فیلد مجاز
VariableModal.vuebuilder/مودال لیست گره‌های قبل + فیلدهای خروجی + دکمه درج
TestRunModal.vuebuilder/انتخاب ورودی آزمایشی: آخرین وب‌هوک / JSON / نمونه / گام‌به‌گام
TestResultPanel.vuebuilder/نتیجه آزمایش: جمع‌بندی + هر گره [ورودی/خروجی/خطا]
NodeErrorBadge.vuebuilder/بج قرمز روی گره + جزئیات شناور با اکشن
ValidatePanel.vuebuilder/لیست خطاهای گراف پیش از انتشار با لینک پرش به گره
VersionList.vuebuilder/لیست نسخه‌ها + دکمه بازگردانی
TopBar.vuebuilder/نوار بالا: نام، وضعیت، undo/redo، ذخیره، انتشار
StatusBar.vuebuilder/نوار پایین: ذخیره، تعداد گره، آخرین اجرا، دکمه آزمایش
CommandPalette.vuebuilder/جست‌وجوی سراسری ⌘K: گره‌ها + اکشن‌ها + پرش سریع
ShortcutHelp.vuebuilder/مودال راهنمای همه شورتکات‌ها (?)
ConflictModal.vuebuilder/حل تداخل ویرایش هم‌زمان چند کاربر
UpgradePrompt.vuebuilder/مودال «این گره به پلن/ماژول دیگری نیاز دارد»
مجموع: ۳۵ کامپوننت. از این تعداد، ۱۱ کامپوننت فیلد فرم قلب تپنده معماری‌اند — بقیه پوسته‌اند. اولویت توسعه: DynamicForm + سه فیلد پرکاربرد (text، select، textarea) در اسپرینت اول فرانت.

۱۷ معماری فنی و Pinia Store

۱۷.۱ ساختار Store

// 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>;
}

۱۷.۲ جریان داده (Data Flow)

  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)حجم بزرگ — فقط وقتی لازم است لود شود

۱۸ معیارهای موفقیت و تست کاربردپذیری

۱۸.۱ شاخص‌های کلیدی (KPI)

شاخصتعریفهدف فاز ۱ابزار سنجش
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 در ۶ اسپرینت دو‌هفته‌ای موازی با توسعه بک‌اند (تیم فرانت ۱ نفر).

Sprint F1 — اسکلت و کانواس پایه هفته ۱–۲
  • نصب Vue Flow + راه‌اندازی FlowCanvas با زوم/پن/minimap
  • BaseNode + سه نوع گره (Trigger/Action/Condition)
  • TopBar + StatusBar + چیدمان ۵ ناحیه
  • اتصال پایه بین گره‌ها + ذخیره موقعیت در Store
قابل نمایشپایه تعامل
Sprint F2 — پالت و پیکربندی پویا هفته ۳–۴
  • NodePalette + جست‌وجو + کشیدن روی کانواس
  • DynamicForm + فیلدهای text/select/textarea
  • خواندن schema از GET /nodes/types
  • ذخیره خودکار (debounce) + Undo/Redo
اولین فرم واقعی
Sprint F3 — متغیر و اجرای آزمایشی هفته ۵–۶
  • VariableModal با منطق «فقط گره‌های قبل»
  • TestRunModal + TestResultPanel
  • انیمیشن پیشرفت اجرا روی کانواس (RunProgress)
  • حالت Dry-Run و تفکیک بج آزمایشی/واقعی
اعتمادسازی کاربر
Sprint F4 — خطا، انتشار و نسخه هفته ۷–۸
  • ValidatePanel + NodeErrorBadge
  • گردش انتشار (Publish) + VersionList + بازگردانی
  • کیبورد شورتکات‌ها + CommandPalette
  • حالت‌های خالی/بارگذاری/آفلاین
پایداری تجربه
Sprint F5 — واکنش‌گرایی و دسترسی‌پذیری هفته ۹–۱۰
  • سه حالت نمایشی (دسکتاپ/تبلت/فقط-خواندنی)
  • ARIA labels + نمای جدولی جایگزین کانواس
  • حالت کنتراست بالا + کاهش حرکت
  • تست کاربردپذیری با ۵ کاربر واقعی + اصلاح یافته‌ها
آماده فروش
Sprint F6 — سخت‌سازی و تحویل هفته ۱۱–۱۲
  • بقیه فیلدهای فرم (date/key_value/expression/picker)
  • بهینه‌سازی عملکرد: virtualization لیست‌ها، lazy Monaco
  • تله‌متری رویدادها برای KPIهای بخش ۱۸
  • مستندات راهنمای درون‌برنامه‌ای (onboarding tour)
پایان فاز ۱ فرانت

۲۰ جمع‌بندی و گام بعدی

۲۰.۱ سند در یک نگاه

۵ ناحیه ثابت

پالت · نوار بالا · کانواس · پنل پیکربندی · نوار وضعیت

۳۵ کامپوننت

۹ کانواس · ۱۳ فرم و پالت · ۱۳ متغیر/تست/پیام

۱۶ شورتکات

ذخیره · undo · پالت · تست · راهنما

۶ KPI

از Time-to-First-Flow تا تیکت پشتیبانی

۴ سطح خطا

فیلد · گره · گراف · سیستمی

۳ فیلد حیاتی

متن · انتخابی · چندخطی (اول توسعه)

۶ اسپرینت

~۳ ماه با یک توسعه‌دهنده فرانت

۱ اصل طلایی

فرم هرگز کدنویسی نمی‌شود؛ از schema ساخته می‌شود

گام بعدی پیشنهادی: سند ۰۵ — سیستم PlanGate و Usage Metering؛ شامل معماری بررسی پلن، شمارنده مصرف، رفتار سقف، overage و صورت‌حساب. سپس سند ۰۶ — Sprint Plan فاز ۱ که همه تسک‌های بک‌اند و فرانت را در یک برنامه واحد جمع می‌کند.