刘光辉
5 小时以前 06f314545ac3514d7ce28939920866ae8188d31c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
// Fixed server-side code. WatermarkInput is decoded from the job's structured JSON data.
builderJS.OpenFile(WatermarkInput.sourceUrl);
var outputFormat = 'docx';
var outputName = 'Watermark.docx';
try {
    var doc = Api.GetDocument();
    if (typeof doc.AddDrawingToPage !== 'function') throw new Error('UNSUPPORTED_VERSION');
    var pageCount = doc.GetPageCount();
    var plans = [];
    var pageAnchors = {};
    var endPosition = doc.GetRange().GetEndPos();
    function pageAnchor(page) {
        if (pageAnchors[page]) return pageAnchors[page];
        // GoToPage can leave the cursor on an earlier page of the same paragraph.
        // Locate the first text position on the physical page independently of that cursor.
        var low = 0;
        var high = endPosition;
        while (low < high) {
            var middle = Math.floor((low + high) / 2);
            if (doc.GetRange(middle, middle).GetStartPage() < page - 1) low = middle + 1;
            else high = middle;
        }
        var range = doc.GetRange(low, low);
        if (range.GetStartPage() !== page - 1) throw new Error('PAGE_ANCHOR_NOT_FOUND|' + page);
        pageAnchors[page] = { range: range, position: low };
        return pageAnchors[page];
    }
    WatermarkInput.overlays.forEach(function (overlay, groupIndex) {
        overlay.pages.forEach(function (page) {
            // The stored Word page count can differ from OnlyOffice pagination.
            // Ignore watermark targets that do not exist in the rendered document.
            if (page > pageCount) return;
            var anchor = pageAnchor(page);
            if (!anchor.range.MoveCursorToPos(anchor.position)) throw new Error('PAGE_ANCHOR_NOT_FOUND|' + page);
            var paragraph = doc.GetCurrentParagraph();
            var section = paragraph && paragraph.GetSection();
            if (!section) throw new Error('PAGE_SECTION_NOT_FOUND|' + page);
            var width = section.GetPageWidth() * 25.4 / 1440;
            var height = section.GetPageHeight() * 25.4 / 1440;
            var variant = overlay.variants.find(function (item) {
                return Math.abs(item.widthMm - width) < 0.2 && Math.abs(item.heightMm - height) < 0.2;
            });
            if (!variant) throw new Error('PAGE_SIZE_NOT_FOUND|' + page);
            plans.push({ page: page, group: groupIndex, variant: variant, position: anchor.position });
        });
    });
    var tracked = doc.IsTrackRevisions();
    doc.SetTrackRevisions(false);
    // Earlier character positions remain stable when drawings are inserted from the last page.
    plans.sort(function (left, right) { return right.page - left.page; });
    plans.forEach(function (plan) {
        if (doc.GetPageCount() !== pageCount) throw new Error('PAGINATION_CHANGED');
        if (!doc.GetRange(plan.position, plan.position).MoveCursorToPos(plan.position)) {
            throw new Error('PAGE_ANCHOR_NOT_FOUND|' + plan.page);
        }
        var variant = plan.variant;
        var drawingWidthMm = variant.drawingWidthMm || variant.widthMm;
        var drawingHeightMm = variant.drawingHeightMm || variant.heightMm;
        var offsetXMm = variant.offsetXMm || 0;
        var offsetYMm = variant.offsetYMm || 0;
        var drawing = Api.CreateImage('data:image/png;base64,' + variant.pngBase64,
            Math.round(drawingWidthMm * 36000), Math.round(drawingHeightMm * 36000));
        drawing.SetName(WatermarkInput.markerPrefix + '_' + plan.group + '_' + plan.page);
        drawing.SetWrappingStyle('behind');
        if (!doc.AddDrawingToPage(drawing, plan.page - 1,
                Math.round(offsetXMm * 36000), Math.round(offsetYMm * 36000))) {
            throw new Error('INSERT_FAILED|' + plan.page);
        }
    });
    doc.SetTrackRevisions(tracked);
    if (doc.GetPageCount() !== pageCount) throw new Error('PAGINATION_CHANGED');
} catch (error) {
    // Return a bounded diagnostic as a separate artifact, never a partly watermarked document.
    var failedDoc = Api.GetDocument();
    failedDoc.SetTrackRevisions(false);
    failedDoc.RemoveAllElements();
    var diagnostic = Api.CreateParagraph();
    diagnostic.AddText('DMS_WATERMARK_ERROR:' + String(error.message).slice(0, 300));
    failedDoc.Push(diagnostic);
    outputFormat = 'txt';
    outputName = 'WatermarkError.txt';
}
builderJS.SaveFile(outputFormat, outputName);
builderJS.CloseFile();