التعليقات التوضيحية

إضافة دعم التعليقات التوضيحية إلى العارض

تعمل التعليقات التوضيحية في Doconut في اتجاهين: يرسمها المستخدمون في ودجت المتصفح ويخزنها الخادم لكل صفحة، أو يبنيها الكود الخاص بك برمجياً ويحملها في جلسة مفتوحة. في كلتا الحالتين تُعرض على الصفحات ويمكن دمجها في تصديرات PDF/PNG.

يتم التحكم في دعم التعليقات التوضيحية عبر قدرة الترخيص Annotation (تُمنح تلقائياً تحت ترخيص مؤقت نشط).

تمكين واجهة المستخدم للتعليقات التوضيحية

التعليق التوضيحي هو وحدة Viewer، وليس شريط أدوات مستقل. يجب أن تشمل الصفحة الكاملة موارد Viewer، شريط أدوات Viewer، نقطة تثبيت Viewer، وobjViewer المُهيأ؛ ثم يتم تثبيت شريط التعليقات التوضيحية وربطه بنفس المثيل.

أصدر حزم التعليقات التوضيحية جنبًا إلى جنب مع حزم العارض — فهي مقيدة بالترخيص، لذا تظهر العلامات فقط عندما تكون القدرة متاحة:

html
@Html.Raw(Viewer.ReferenceCss(new CssConfig
{
    IncludeViewerCss     = true,
    IncludeAnnotationCss = true   // jquery-ui.min.css + annotationBar.css
}))

@Html.Raw(Viewer.ReferenceScripts(new ScriptConfig
{
    IncludeJQuery             = true,
    IncludeViewerScripts      = true,
    IncludeAnnotationScripts  = true, // jquery-ui, raphael.js, annotation.js
    IncludeAnnotationBar      = true  // the embedded annotation ribbon
}))

احتفظ بتركيب Viewer الكامل مرئيًا في العلامات:

html
<nav id="toolbar" aria-label="Document viewer controls">
    <!-- Viewer controls, including the button that opens Annotation -->
</nav>
<div id="annBarMount"></div>
<div id="divDocViewer"><div id="div_ctlDoc"></div></div>

حزمة التعليقات التوضيحية تُنشئ شريط الـ Ribbon داخل annBarMount؛ لا تحتاج إلى نسخ أزراره أو علامات الحوار. قم بتهيئة docViewer أولاً، ثم أنشئ الـ Ribbon فقط عندما يؤكد الخادم أن التعليق التوضيحي مرخص:

html
<script>
    let annBar = null;
    let currentToken = '';

    const objViewer = $('#div_ctlDoc').docViewer({
        BasePath: '/doconut',
        ResPath: '/doconut-res/images',
        onAnnLoaded:    () => annBar?.handleAnnLoaded(),
        onAnnSaved:     () => annBar?.handleAnnSaved(),
        onAnnSaveError: () => annBar?.handleAnnSaveError(),
        onAnnClosed:    () => annBar?.handleAnnClosed(),
        onError:        (message) => console.error('Viewer error:', message)
    });

    @if (Viewer.IsAnnotationEnabled)
    {
        <text>
    annBar = $('#annBarMount').doconutAnnotationBar({
        docId: 'ctlDoc',
        getRequestParams: () => ({ token: currentToken }),
        onStatus: (message) => console.log(message),
        onToast: (message, type) => console.log(type, message),
        onLayout: () => requestAnimationFrame(() => objViewer.Refit())
    });
    annBar.attach(objViewer);
        </text>
    }
</script>

حفظ البيانات من الـ Ribbon يرسلها عبر الطبقة الوسيطة (AnnSave)، التي تخزنها في جلسة المستند لكل صفحة. يتم تحميلها (AnnLoad) تلقائيًا عندما يُعرض صفحة تحتوي على تعليقات توضيحية. تُبقي الاستدعاءات الأربعة onAnn* الـ Ribbon متزامنًا مع دورة حياة العارض.

افتحه وأغلقه من أي شريط أدوات Viewer مملوك للمضيف:

javascript
annBar.open();
annBar.close();

واجهة برمجة تطبيقات الـ Ribbon العامة هي:

الطريقةالغرض
attach(objViewer)ربط الـ Ribbon بالعارض المُهيأ؛ مطلوب مرة واحدة
open() / close()بدء أو إنهاء تحرير التعليقات التوضيحية
reset()إرجاع الـ Ribbon إلى حالته المغلقة غير القابلة للتحرير
isOpen() / annotating()قراءة حالة الـ Ribbon / حالة تحرير التعليقات في العارض
reopenEditable()إعادة تحميل تعليقات الصفحة الحالية ككائنات قابلة للتحرير
updateActionState()تحديث توفر عناصر التحكم حفظ/حذف بعد تغييرات المضيف
headerSlot()الحصول على فتحة التوسعة الاختيارية للرأس للتحكمات المملوكة للمضيف

onStatus، onToast، onLayout، onEditStart، وonEditEnd هي استدعاءات مضيف اختيارية. يمكن لكائن endpoints أيضًا توفير exportPdf، exportPng، imageUpload، وimageList؛ تظل عناصر التحكم التي لا تُعَدّ نقطة نهاية مخفية. لسلسلة بدء تشغيل Viewer المدمج مع البحث والتعليقات التوضيحية، راجع البدء السريع(Quick Start).

تضيف حزمة التعليقات التوضيحية أدوات التأليف في المتصفح، لكن البيانات لا تزال تعود إلى جلسة المستند على الخادم المحددة بالرمز المميز. إعادة فتح المصدر تُنشئ جلسة جديدة؛ احفظ ملف XML أو ظرف التعليقات المشفر في تطبيقك إذا كان يجب أن تبقى التعليقات بعد انتهاء الجلسة.

بناء التعليقات التوضيحية في C#

احصل على مدير مرتبط بالجلسة المفتوحة، أضف تعليقات توضيحية، وحمّلها (مع using Doconut.Annotations; للأنواع وusing System.Drawing; لـ Rectangle/Color):

csharp
app.MapPost("/api/annotations/load-sample", (string token, Viewer viewer) =>
{
    // Bound to the open session's page dimensions
    var manager = viewer.GetAnnotationManager(token);
    var pageCount = viewer.GetPageCount(token);

    // One stamp per page
    for (int page = 1; page <= pageCount; page++)
    {
        manager.Add(new StampAnnotation(page, new Rectangle(30, 20, 240, 90),
            $"PAGE {page}", 28, 4, Color.Maroon)
        {
            Opacity = 60,
            Rotate  = -8
        });
    }

    manager.Add(new NoteAnnotation(1, new Rectangle(420, 150, 220, 120),
        "Loaded from C# code.", Color.FromArgb(255, 255, 255, 170), 14));

    // Load into the session — the widget fetches them via AnnLoad and the
    // renderer burns them into image/PDF exports.
    viewer.LoadAnnotationData(token, manager);
    return Results.Ok();
});

أنواع التعليقات التوضيحية

جميع الأنواع موجودة في Doconut.Annotations وتورث من BaseAnnotation (رقم الصفحة + Rectangle المحدد):

النوعملاحظات
StampAnnotationختم نصي بحجم الخط، حد، لون؛ يدعم Opacity، Rotate
NoteAnnotationملاحظة لاصقة بنص، لون خلفية، حجم خط، TitleColor
RectangleAnnotationألوان الحد والملء، Title/ShowTitle
CircleAnnotationحد وملء، ShowBorder
EllipseAnnotationحد وملء، ShowBorder
TriangleAnnotationلون الحد، BackColor، ShowBorder
LineAnnotationخط مستقيم بعرض ولون
ArrowAnnotationخط بسهم؛ يمكن ضبط Direction (من النوع ArrowDirection، نقاط البوصلة، الافتراضي E)
FreehandAnnotationضربة حرة من نقاط FreehandData المشفرة
ImageAnnotationصورة من عنوان URL. يُحل عنوان URL النسبي بالنسبة لمضيف الطلب عندما تُضاف التعليقة (يتم فقط جلب الصورة عند الدمج) — يجب أن تكون قابلة للوصول من الخادم (مثلاً ملف تحت wwwroot يُخدم عبر UseStaticFiles)

واجهة برمجة تطبيقات AnnotationManager

العضوالغرض
Add(BaseAnnotation)إضافة تعليق إلى الطابور
GetAnnotations() / GetAnnotations(int page)فحص ما يحتفظ به المدير
ClearAnnotations() / ClearAnnotations(int page)إزالة جميع التعليقات / حسب الصفحة
GetAnnotationData() / GetAnnotationData(int page)سلسلة بيانات التعليق المشفرة — ظرف Base64 (ما يستهلكه الودجت)
GetAnnotationXml()صيغة XML

Viewer يعكس عمليات التحميل/القراءة مقابل جلسة: LoadAnnotationData(token, manager) أو LoadAnnotationData(token, encodedData) (ظرف Base64 من GetAnnotationData()LoadAnnotationXML(token, xml)، GetAnnotationXML(token).

التصدير مع دمج التعليقات التوضيحية

csharp
// PDF of all pages with annotations rendered onto them
app.MapGet("/api/annotations/export-pdf", async (string token, Viewer viewer) =>
{
    byte[] pdf = await viewer.ExportAnnotationsToPdfAsync(token, zoom: 100);
    return Results.File(pdf, "application/pdf", "export.pdf");
});

// Or a ZIP of per-page PNGs
app.MapGet("/api/annotations/export-png-zip", async (string token, Viewer viewer) =>
{
    byte[] zip = await viewer.ExportAnnotationsToPngZipAsync(token, zoom: 100);
    return Results.File(zip, "application/zip", "annotations-png.zip");
});

تستخدم عمليات التصدير نفس أداة الدمج المستخدمة في العرض على الشاشة، لذا ما يراه المستخدمون هو ما يحتويه الملف.

سير عمل الاستمرار

  1. افتح المستند واحصل على رمزه المميز.
  2. حمّل XML أو البيانات المشفرة المخزنة مسبقًا إلى ذلك الرمز.
  3. دع الودجت يقرأ ويحرّر تعليقات الجلسة.
  4. استرجع XML باستخدام GetAnnotationXML(token) عندما يقرر تطبيقك حفظه.
  5. صدّر PDF/PNG عندما تكون نسخة مسطحة مطلوبة.
  6. أغلق جلسة المستند.

لا تستخدم الرمز المميز للعارض كمعرّف دائم للتعليقات. اربط بيانات التعليقات المستمرة بمعرفات المستند والإصدار الخاصة بك.

ملاحظات الأمان والعرض

  • طلبات التعليقات التوضيحية تستخدم نفس أمان الجلسة/الرمز المميز كما في طلبات الصفحات.
  • يُحل عنوان URL نسبي لـ ImageAnnotation من مضيف الطلب ويجب أن يبقى قابلًا للوصول إلى الخادم عند الدمج.
  • تحقق من أي عنوان URL للصورة يقدمه المستخدم وتحكم فيه لتجنب تزوير طلبات الخادم.
  • تُطبق التصديرات نفس قرار الترخيص/العلامة المائية المخصصة كما في عرض الصفحات على الشاشة.
  • الأحمال الكبيرة للخط الحر والتصديرات عالية الدقة تزيد من استهلاك الذاكرة؛ اختبر المستندات والقيم التكبيرية الواقعية.

استكشاف الأخطاء وإصلاحها

العَرَضالفحص
شريط الـ Ribbon مفقودقدرة Annotation وعلامات CSS/Script الأربعة للتعليقات
استدعاء الحفظ يُبلغ عن خطأانتهاء صلاحية الرمز/الجلسة وإعداد BasePath للطبقة الوسيطة
تعليقات C# لا تظهرترقيم الصفحات يبدأ من الواحد والبيانات تم تحميلها إلى الرمز النشط
صورة التعليق تظهر على الشاشة لكنها لا تظهر في التصديريستطيع الخادم الوصول إلى عنوان URL للصورة أثناء الدمج
المستند المعاد فتحه لا يحتوي على تعليقاتاحفظ XML/البيانات خارج جلسة العارض، ثم حمّلها إلى الرمز الجديد

هل كانت هذه الصفحة مفيدة؟