التعليقات التوضيحية
Add annotation support to the viewer
التعليقات التوضيحية في Doconut تعمل في اتجاهين: يرسمها المستخدمون في عنصر الواجهة بالمتصفح ويقوم الخادم بحفظها لكل صفحة، أو يبنيها الكود برمجياً ويحمّلها في جلسة مفتوحة. في كلتا الحالتين تُعرض على الصفحات ويمكن دمجها في تصديرات PDF/PNG.
دعم التعليقات التوضيحية مقيد بميزة الترخيص Annotation (يُمنح تلقائياً بموجب ترخيص مؤقت نشط).
تمكين واجهة التعليقات التوضيحية
التعليقات التوضيحية هي وحدة Viewer، ليست شريط أدوات مستقل. يجب أن تتضمن الصفحة الكاملة موارد Viewer، شريط أدوات Viewer، تثبيت Viewer، وobjViewer المُهيأ؛ ثم يتم تثبيت شريط التعليقات التوضيحية (Annotation Ribbon) وإرفاقه بنفس المثيل.
أصدر حزم التعليقات التوضيحية جنباً إلى جنب مع حزم العارض — فهي مقيدة بالترخيص، لذا تظهر العلامات فقط عندما تكون الميزة متاحة:
@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 الكامل مرئياً في العلامات:
<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 أولاً، ثم أنشئ الشريط فقط عندما يؤكد الخادم أن التعليقات التوضيحية مرخصة:
<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 مملوك للمضيف:
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):
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).
تصدير مع دمج التعليقات
// 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");
});تستخدم عمليات التصدير نفس أداة الحرق كما في العرض على الشاشة، لذا ما يراه المستخدمون هو ما يحتويه الملف.
سير عمل الحفظ
- افتح المستند واحصل على رمزه.
- حمّل XML أو البيانات المشفرة المخزنة مسبقًا إلى ذلك الرمز.
- اسمح للودجت بقراءة وتحرير تعليقات الجلسة.
- استرجع XML باستخدام
GetAnnotationXML(token)عندما يقرر تطبيقك حفظ البيانات. - صدّر PDF/PNG عندما يكون التسليم المسطح مطلوبًا.
- أغلق جلسة المستند.
لا تستخدم رمز المشاهد غير الشفاف كمعرف دائم للتعليقات. اربط بيانات التعليقات المخزنة بمعرفات المستند والإصدار الخاصة بك.
ملاحظات الأمان والعرض
- تستخدم طلبات التعليقات التوضيحية نفس أمان الجلسة/الرمز المميز كما في طلبات الصفحات.
- يتم حل عنوان URL النسبي لـ
ImageAnnotationمن مضيف الطلب ويجب أن يظل قابلاً للوصول إلى الخادم عند وقت الحرق. - تحقق من صحة أي عنوان URL للصور مقدم من المستخدم وتَحكم فيه لتجنب تزوير طلبات الخادم.
- تطبق الصادرات نفس قرار الترخيص/العلامة المائية المخصصة كما في عرض الصفحات على الشاشة.
- تزيد الحمولات الكبيرة باليد الحرة والصادرات عالية الدقة من استهلاك الذاكرة؛ اختبر المستندات الواقعية وقيم التكبير.
استكشاف الأخطاء وإصلاحها
| العَرَض | التحقق |
|---|---|
| شريط التعليقات التوضيحية مفقود | Annotation القدرة والأعلام الأربعة لـ CSS/السكريبت الخاصة بالتعليقات التوضيحية |
| إبلاغ رد النداء للحفظ عن خطأ | انتهاء صلاحية Token/session والوسيط BasePath |
| التعليقات التوضيحية بـ C# لا تظهر | ترقيم الصفحات يبدأ من الواحد وتم تحميل البيانات إلى الرمز المميز النشط |
| تظهر التعليقات التوضيحية للصور على الشاشة ولكن ليس في التصدير | يمكن للخادم الوصول إلى عنوان URL للصورة أثناء عملية الحرق |
| المستند المفتوح مرة أخرى لا يحتوي على تعليقات توضيحية | احفظ XML/البيانات خارج جلسة المشاهد، ثم حمّلها إلى الرمز المميز الجديد |
هل كانت هذه الصفحة مفيدة؟