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

Add annotation support to the viewer

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

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

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

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

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

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 أولاً، ثم أنشئ الشريط فقط عندما يؤكد الخادم أن التعليقات التوضيحية مرخصة:

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>

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

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

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

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

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

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

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

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

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

csharp
app.MapPost("/api/annotations/load-sample", (string token, Viewer viewer) =>
{
    // مرتبط بأبعاد صفحة الجلسة المفتوحة
    var manager = viewer.GetAnnotationManager(token);
    var pageCount = viewer.GetPageCount(token);

    // ختم واحد لكل صفحة
    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));

    // تحميل إلى الجلسة — الودجت يجلبها عبر AnnLoad و
    // أداة العرض تحرقها في تصديرات الصورة/PDF.
    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 لجميع الصفحات مع تعليقات مرسومة عليها
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");
});

// أو ملف ZIP من PNG لكل صفحة
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 للصور مقدم من المستخدم وتَحكم فيه لتجنب تزوير طلبات الخادم.
  • تطبق الصادرات نفس قرار الترخيص/العلامة المائية المخصصة كما في عرض الصفحات على الشاشة.
  • تزيد الحمولات الكبيرة باليد الحرة والصادرات عالية الدقة من استهلاك الذاكرة؛ اختبر المستندات الواقعية وقيم التكبير.

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

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

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