مرجع BI — وضع المعالج (Wizard Mode)
مرفق بـ bi-module-technical-reference.md. يُحمَّل هذا الملف فقط عند تأليف widget تم فيها تعيين wizardDataSource.
عندما يحتوي widget على wizardDataSource، يشير chartConfigJSON إلى معرّفات حقول المعالج (wizard field IDs) بدلاً من أسماء أعمدة SQL الخام. يُحلّل الخادم كل معرّف إلى اسم مستعار SQL من البيانات الوصفية المخزّنة مؤقتاً؛ لا تتأثر widgets وضع SQL بأي شيء هنا.
1. التخزين المؤقت للبيانات الوصفية (Metadata caching)
عند حفظ DashBoardWidgetWizard، يُشغِّل postCommitAction دالة ReportWizardQuery.build() مرة واحدة ويخزّن البيانات الوصفية لكل حقل في JSON الخاصة بالنظام fieldMetadata في كل سطر:
fieldId— مسار خاصية حقل المعالجchartUsage—Dimension|MeasureparamType—Reference,Decimal,Text,Date,Integer,Genericreference,Enum,BooleanreferencedEntityType— لحقول المرجع فقطaggregation—None,Sum,Count,Average,Min,MaxdisplayAlias— الاسم المستعار SQL لعمود العرض الأساسي للحقلsubColumns— لحقول المرجع فقط: أسماء مستعارة للأعمدة الفرعية الموسّعة تلقائياً id/code/name1/name2/entityType/valuesqlLeftHandSide— الجانب الأيسر المؤهل بالكامل المستخدم لحقن WHERE في الفلاتر المتقاطعةarabicTitle/englishTitle— يُمرَّران كما هما
يُفكّك البحث عند التصيير السجلات المخزّنة مؤقتاً — دون إعادة بناء ReportWizardQuery.
2. مفاتيح تعيين البيانات (Data-mapping keys)
لكل فتحة عمود في §3 من المرجع الرئيسي، يضيف وضع المعالج نظيراً *WizardFieldId:
| مفتاح SQL | نظير المعالج | يُحلَّل إلى |
|---|---|---|
categoryColumn | categoryWizardFieldId | displayAlias |
labelColumn | labelWizardFieldId | نفسه |
valueColumn | valueWizardFieldId | نفسه |
xColumn / yColumn | xWizardFieldId / yWizardFieldId | نفسه |
sizeColumn | sizeWizardFieldId | حجم فقاعة Scatter |
innerLabelColumn / outerLabelColumn | innerLabelWizardFieldId / outerLabelWizardFieldId | حلقات NestedLabelValue |
innerValueColumn / outerValueColumn | innerValueWizardFieldId / outerValueWizardFieldId | قياسات NestedLabelValue |
leftValueColumn / rightValueColumn | leftValueWizardFieldId / rightValueWizardFieldId | FunnelComparison |
series[].column | series[].wizardFieldId | نفسه |
maxResultsRankBy | maxResultsRankByWizardFieldId | قياس الترتيب top-N |
عند وجود المفتاحين معاً → يسود *Column. أعمدة Tempo / مقارنة الفترات ليست حقول معالج؛ استخدم *Column فقط — يُتجاهل wizardFieldId بصمت.
"dataMapping": {
"type": "CategoryLabelValue",
"categoryWizardFieldId": "invoice.valueDate",
"labelWizardFieldId": "customer.customerCategory",
"valueWizardFieldId": "price.netValue",
"seriesType": "bar"
}3. إصدار النقر والتنقل التفصيلي مع wizardFieldId
"clickEmitMapping": [
{ "crossFilterCode": "customerCategoryFilter", "wizardFieldId": "customer.customerCategory" }
]لكل إدخال يحتوي على wizardFieldId:
- استنتاج الأعمدة الفرعية — يملأ الخادم الأعمدة المفقودة
idColumn/codeColumn/name1Column/name2Column/entityTypeColumn/valueColumn/entityTypeمنsubColumnsالمخزّنة +referencedEntityType. - الفلترة لكل محدد — يُطلق الإدخال فقط عندما يكون
wizardFieldIdالخاص به ضمن المحددات النشطة حالياً (انظر §4 أدناه).
الإدخالات التي لا تحتوي على wizardFieldId دائماً نشطة (سلوك وضع SQL القديم).
4. المحددات النشطة (Active dimensions)
قائمة "المحددات النشطة حالياً" بالترتيب:
- إذا كان الطلب يحمل
drillDownByTargetDimension، يكون معرّف الحقل هذا أولاً. - ثم
categoryWizardFieldId,labelWizardFieldId,xWizardFieldId,yWizardFieldId— أيها كان مُعيَّناً فيdataMapping.
يُتخطى المكرر. تقود هذه القائمة:
- إعادة بناء SQL عبر
ReportWizardQuery.buildForDrillDown(wizard, primary, otherDims). يصبح الأساسي أول GROUP BY؛ تُلحَق الأخرى؛ تبقى القياسات. - فلترة النقر/التفصيل (§3 أعلاه).
- استبعاد قائمة التنقل التفصيلي — المحددات النشطة بالفعل مخفية من قائمة "Drill Down By" عند النقر بالزر الأيمن.
5. دلالات التنقل التفصيلي — الخيار أ (Drill-by semantics - Option A)
عندما ينقر المستخدم بالزر الأيمن ← "Drill Down By X":
- الفئة تُستبدل — يأخذ المحدد المُنقَّل إليه المكان الأساسي.
- المحددات النشطة الأخرى (label, x, y) تبقى — يُحافَظ على شكل الرسم البياني.
- تراكم مكدس التنقل: إدخال واحد لكل تنقل
(categoryFieldId, clickedValue). القيمة المنقور عليها للـ label لا تُضاف. - تتراكم الفلاتر (بعد تنقلين:
WHERE month='Jan' AND region='West').
قائمة التنقل = wizard.fields مفلترة إلى chartUsageType=Dimension وغير موجودة في القائمة النشطة وغير موجودة في مكدس التنقل.
بعد التنقل، يقرأ الخادم chartConfigJSON الموجود ويُعيد كتابة dataMapping.categoryColumn بـ displayAlias الخاص بالمحدد المُنقَّل إليه (ويحذف categoryWizardFieldId). كل شيء آخر — echartOption، valueColumn/valueWizardFieldId، تنسيق السلاسل، الألوان، التعيينات — يُنقل كما هو.
6. جانب الفلتر المتقاطع الأيسر SQL (Cross-filter SQL LHS)
يقبل الجانب الأيسر للفلتر المتقاطع في widget المعالج (على الربط أو على BICrossFilter) مسار حقل المعالج بالإضافة إلى alias.column الخام. أي حقل يمكن الوصول إليه من الكيان الرئيسي للمعالج صالح — لا يلزم عرضه.
قيم LHS الصالحة:
customer— حقل مرجع على الكيان الرئيسي. يرتبط تلقائياً بالمعرّف المُشار إليه.customer.salesman.code— مسار خاصية عبر ضمتين. تُضاف الضمات عند الحاجة.valueDate— عمود عددي على الكيان الرئيسي.l.branch_id— alias.column خام (قديم؛ لا يزال يعمل).
يُعامل المصنّف نقطتين أو أكثر، أو قيمة يتم حلّها مقابل نموذج بيانات الجدول الرئيسي، كمسار معالج؛ وإلا فهو SQL خام.
7. التعايش مع الـ widgets القديمة (Coexistence with legacy widgets)
الـ widgets ذات المعالج الموجودة مسبقاً (بدون مفاتيح *WizardFieldId، فقط *Column) تُقرأ كما كانت — أسماء أعمدة، بدون فلترة لكل محدد. إعادة الحفظ عبر مصمم الرسوم البيانية يُرقّي الـ widget إذا اختار المستخدم معرّفات الحقول.
8. مثال كامل (Complete example)
{
"echartOption": {
"tooltip": {"trigger": "axis", "axisPointer": {"type": "shadow"}},
"legend": {},
"xAxis": {"type": "category", "data": "$DATA.categories"},
"yAxis": {"type": "value"},
"series": "$DATA.series"
},
"dataMapping": {
"type": "CategoryLabelValue",
"categoryWizardFieldId": "invoice.valueDate",
"labelWizardFieldId": "customer.customerCategory",
"valueWizardFieldId": "price.netValue",
"seriesType": "bar",
"stack": "total"
},
"clickEmitMapping": [
{ "crossFilterCode": "dateFromFilter", "wizardFieldId": "invoice.valueDate" },
{ "crossFilterCode": "customerCategoryFilter", "wizardFieldId": "customer.customerCategory" }
],
"drillDownMapping": [
{
"key": "categoryDetails",
"wizardFieldId": "customer.customerCategory",
"targetWidgetCode": "bi-category-details",
"enTitle": "Category details", "arTitle": "تفاصيل التصنيف",
"filters": [
{ "crossFilterCode": "customerCategoryFilter", "wizardFieldId": "customer.customerCategory" }
]
}
]
}المعالج:
{
"code": "bi-sales-breakdown",
"type": "EChartDataSource",
"tableType": "DetailLine",
"mainTable": "SalesInvoiceLine",
"fields": [
{"fieldId": "invoice.valueDate", "chartUsageType": "Dimension"},
{"fieldId": "customer.customerCategory", "chartUsageType": "Dimension"},
{"fieldId": "price.netValue", "chartUsageType": "Measure", "sqlAggregationType": "Sum"}
]
}9. اختيار الفتحة في وقت التشغيل (Runtime slot selection)
تعرض widgets المعالج أداة اختيار في وقت التشغيل (شريط الأدوات / أيقونة صندوق أدوات echarts) حتى يتمكن المشاهدون من تبديل محدد الفئة، وتغيير القياسات، أو إضافة سلاسل — لجلسة العمل الحالية فقط.
| نوع التعيين | فتحات المحددات | فتحات القياسات | سلاسل متعددة القياسات |
|---|---|---|---|
CategoryValue | categoryWizardFieldId | series[].wizardFieldId (N) | نعم (flexible فقط) |
LabelValue | labelWizardFieldId | valueWizardFieldId | لا |
CategoryLabelValue | categoryWizardFieldId, labelWizardFieldId | valueWizardFieldId | لا |
Scatter | — | xWizardFieldId, yWizardFieldId, sizeWizardFieldId | لا |
Heatmap | xWizardFieldId, yWizardFieldId | valueWizardFieldId | لا |
Gauge | — | valueWizardFieldId | لا |
Tree | labelWizardFieldId | valueWizardFieldId | لا |
Waterfall, NestedLabelValue, GaugeMulti, Radar, FunnelComparison, Custom, Raw ← لا يوجد أداة اختيار في وقت التشغيل.
CategoryValue مرن مقابل ثابت: يكون CategoryValue "مرناً" فقط عندما تكون جميع إدخالات series[] موحّدة — نفس type، بدون yAxisIndex، بدون stack، بدون target. الرسوم البيانية ذات المحورين / bar+line المدمج / المكدّسة / ذات الهدف ثابتة: يُخفى منتقي متعدد القياسات.
لا أداة اختيار في وضع التنقل التفصيلي: عندما يحمل الطلب drillDownByTargetDimension، يحذف الخادم runtimeSelectorInfo.
أعلام الإلغاء على chartConfigJSON:
disableRuntimeDimensionSelection: true— يُخفي منتقيات المحددات (يبقي القياسات).disableRuntimeMeasureSelection: true— يُخفي منتقيات القياسات (يبقي المحددات).
ضبط كليهما على true يُخفي أداة الاختيار بالكامل.
النقر/التنقل يتبعان المحددات النشطة: تغييرات الفتحة في وقت التشغيل تُعيد تشكيل activeDimensionFieldIds، لذا تتبع إدخالات النقر والتنقل المفتاحة بـ wizardFieldId المحددات النشطة الجديدة تلقائياً.
توجيه AI: يُفضَّل استخدام مفاتيح وضع المعالج (*WizardFieldId) كلما كان wizardDataSource موجوداً حتى تكتسب widgets أداة الاختيار في وقت التشغيل تلقائياً.