حاشیه‌نویسی‌ها

پشتیبانی از حاشیه‌نویسی را به نمایشگر اضافه کنید

حاشیه‌نویسی‌ها در Doconut در دو جهت کار می‌کنند: کاربران آن‌ها را در ویجت مرورگر می‌کشند و سرور آن‌ها را به ازای هر صفحه ذخیره می‌کند، یا کد شما آن‌ها را به‌صورت برنامه‌نویسی ساخته و در یک جلسه باز بارگذاری می‌کند. به هر حال، این‌ها در صفحات رندر می‌شوند و می‌توانند در خروجی‌های PDF/PNG تعبیه شوند.

پشتیبانی از حاشیه‌نویسی توسط قابلیت مجوز Annotation محدود شده است (به‌صورت خودکار تحت یک مجوز موقت فعال اعطا می‌شود).

فعال‌سازی رابط کاربری حاشیه‌نویسی

حاشیه‌نویسی یک ماژول Viewer است، نه یک نوار ابزار مستقل. صفحه کامل باید شامل منابع Viewer، نوار ابزار Viewer، محل نصب Viewer و objViewer اولیه باشد؛ سپس نوار Ribbon حاشیه‌نویسی نصب و به همان نمونه متصل می‌شود.

بسته‌های حاشیه‌نویسی را همراه با بسته‌های Viewer صادر کنید — آن‌ها تحت مجوز هستند، بنابراین برچسب‌ها فقط زمانی ظاهر می‌شوند که قابلیت موجود باشد:

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>

بسته حاشیه‌نویسی DOM نوار 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 همگام نگه می‌دارند.

از هر نوار ابزار Viewer متعلق به میزبان آن را باز و بسته کنید:

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

API عمومی نوار Ribbon عبارت است از:

متدهدف
attach(objViewer)اتصال نوار Ribbon به Viewer مقداردهی‌شده؛ یک بار مورد نیاز است
open() / close()ورود یا خروج از ویرایش حاشیه‌نویسی
reset()بازگرداندن نوار به حالت بسته و غیر ویرایشی
isOpen() / annotating()خواندن وضعیت نوار / وضعیت ویرایشی حاشیه‌نویسی Viewer
reopenEditable()بارگذاری مجدد حاشیه‌نویسی‌های صفحه جاری به‌عنوان اشیای قابل ویرایش
updateActionState()به‌روزرسانی دسترس‌پذیری کنترل‌های ذخیره/حذف پس از تغییرات میزبان
headerSlot()دریافت اسلات اختیاری سرصفحه برای کنترل‌های متعلق به میزبان

onStatus، onToast، onLayout، onEditStart و onEditEnd کال‌بک‌های اختیاری میزبان هستند. شیء endpoints می‌تواند به‌علاوه exportPdf، exportPng، imageUpload و imageList را فراهم کند؛ کنترل‌هایی که نقطه انتهایی پیکربندی‌شده ندارند مخفی می‌مانند. برای توالی راه‌اندازی ترکیبی Viewer، Search و Annotation، به شروع سریع مراجعه کنید.

بسته حاشیه‌نویسی ابزارهای نویسندگی مرورگر را اضافه می‌کند، اما داده‌ها همچنان به جلسه سند سمت سرور که با توکن شناسایی می‌شود تعلق دارند. بازگشایی منبع یک جلسه جدید ایجاد می‌کند؛ اگر حاشیه‌نویسی‌ها باید پس از پایان عمر جلسه باقی بمانند، 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 relative نسبت به میزبان درخواست هنگام افزودن حاشیه‌نویسی حل می‌شود (فقط دریافت تصویر در زمان سوختن انجام می‌شود) — باید از سمت سرور قابل دسترسی باشد (مثلاً فایلی زیر wwwroot که توسط UseStaticFiles سرو می‌شود)

API مدیریت‌حاشیه‌نویسی

متدکاربرد
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. جلسه سند را ببندید.

از توکن مبهم viewer به عنوان شناسه دائمی حاشیه‌نویسی استفاده نکنید. داده‌های حاشیه‌نویسی ذخیره‌شده را با شناسه‌های سند و نسخه خودتان مرتبط کنید.

نکات امنیتی و رندرینگ

  • درخواست‌های حاشیه‌نویسی از همان امنیت جلسه/توکن همانند درخواست‌های صفحه استفاده می‌کنند.
  • یک URL نسبی ImageAnnotation از میزبان درخواست حل می‌شود و باید در زمان پردازش برای سرور قابل دسترسی باقی بماند.
  • URL تصویر ارائه‌شده توسط کاربر را اعتبارسنجی و کنترل کنید تا از جعل درخواست سمت سرور جلوگیری شود.
  • خروجی‌ها همان تصمیم‌گیری دربارهٔ مجوز/آب‌نشان سفارشی را که در رندر صفحه روی‌صفحه اعمال می‌شود، به کار می‌برند.
  • بارهای آزاد بزرگ و خروجی‌های با وضوح بالا مصرف حافظه را افزایش می‌دهند؛ اسناد واقعی و مقادیر زوم را تست کنید.

عیب‌یابی

علائمبررسی
نوار حاشیه‌نویسی موجود نیستAnnotation قابلیت و چهار پرچم CSS/script حاشیه‌نویسی
بازگشت‌خوان ذخیره خطایی گزارش می‌دهدانقضای توکن/جلسه و میانی‌افزار BasePath
حاشیه‌نویسی‌های C# ظاهر نمی‌شوندشماره‌گذاری صفحات از یک شروع می‌شود و داده‌ها به توکن فعال بارگذاری شده‌اند
حاشیه‌نویسی تصویر روی صفحه نمایش داده می‌شود اما در خروجی نیستسرور می‌تواند در زمان پردازش (burn‑in) به URL تصویر دسترسی داشته باشد
سند بازگشایی‌شده حاشیه‌نویسی نداردXML/داده‌ها را خارج از جلسه نمایش‌گر ذخیره کنید، سپس در توکن جدید بارگذاری کنید

آیا این صفحه مفید بود؟