From 26964d6041d54353695698b0c5aed67d7646caae Mon Sep 17 00:00:00 2001 From: Argo Zhang Date: Tue, 2 May 2023 09:23:43 +0800 Subject: [PATCH] feat(Upload): use JavaScript isolation (#1189) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: 增加更新预览集合方法 * feat: upload 组件使用脚本隔离 * feat: 增加 ShowZoomButton 参数 * test: 更新单元测试 * test: 更新单元测试 --- .../Components/Upload/CardUpload.razor | 15 +- .../Components/Upload/CardUpload.razor.cs | 6 + .../Components/Upload/UploadBase.cs | 2 +- src/BootstrapBlazor/wwwroot/modules/upload.js | 156 ++++++++---------- src/BootstrapBlazor/wwwroot/modules/viewer.js | 4 + test/UnitTest/Components/UploadTest.cs | 33 +++- 6 files changed, 123 insertions(+), 93 deletions(-) diff --git a/src/BootstrapBlazor/Components/Upload/CardUpload.razor b/src/BootstrapBlazor/Components/Upload/CardUpload.razor index 8222cd597..fb0cdc570 100644 --- a/src/BootstrapBlazor/Components/Upload/CardUpload.razor +++ b/src/BootstrapBlazor/Components/Upload/CardUpload.razor @@ -16,7 +16,7 @@ { prevUrl } - else if(IconTemplate != null) + else if (IconTemplate != null) { @IconTemplate(item) } @@ -28,12 +28,15 @@
@item.GetFileName() (@item.Size.ToFileSizeString())
- - @if(ShowDownloadButton) + @if (ShowZoomButton) { - + } + @if (ShowDownloadButton) + { + } diff --git a/src/BootstrapBlazor/Components/Upload/CardUpload.razor.cs b/src/BootstrapBlazor/Components/Upload/CardUpload.razor.cs index 1efd7585c..4a0afcf77 100644 --- a/src/BootstrapBlazor/Components/Upload/CardUpload.razor.cs +++ b/src/BootstrapBlazor/Components/Upload/CardUpload.razor.cs @@ -73,6 +73,12 @@ public partial class CardUpload [Parameter] public string? ZoomIcon { get; set; } + /// + /// 获得/设置 是否显示放大按钮 默认 true + /// + [Parameter] + public bool ShowZoomButton { get; set; } = true; + [Inject] [NotNull] private IIconTheme? IconTheme { get; set; } diff --git a/src/BootstrapBlazor/Components/Upload/UploadBase.cs b/src/BootstrapBlazor/Components/Upload/UploadBase.cs index 313d1d2d1..c32a84b27 100644 --- a/src/BootstrapBlazor/Components/Upload/UploadBase.cs +++ b/src/BootstrapBlazor/Components/Upload/UploadBase.cs @@ -9,7 +9,7 @@ namespace BootstrapBlazor.Components; /// /// Upload 组件基类 /// -[JSModuleAutoLoader("upload", ModuleName = "Upload")] +[JSModuleAutoLoader(ModuleName = "upload")] public abstract class UploadBase : ValidateBase, IUpload { /// diff --git a/src/BootstrapBlazor/wwwroot/modules/upload.js b/src/BootstrapBlazor/wwwroot/modules/upload.js index 7c9a7cf80..798a5eb96 100644 --- a/src/BootstrapBlazor/wwwroot/modules/upload.js +++ b/src/BootstrapBlazor/wwwroot/modules/upload.js @@ -1,93 +1,81 @@ import Data from "./data.js" -import EventHandler from "./base/event-handler.js" -import BlazorComponent from "./base/blazor-component.js" +import EventHandler from "./event-handler.js" +import Viewer from "./viewer.js" -export class Upload extends BlazorComponent { - static get Default() { - return { - browserClass: '.btn-browser' +export function init(id) { + const el = document.getElementById(id) + if (el === null) { + return + } + const preventHandler = e => e.preventDefault() + const upload = { el, preventHandler } + Data.set(id, upload) + + const inputFile = el.querySelector('[type="file"]') + EventHandler.on(el, 'click', '.btn-browser', () => { + inputFile.click() + }) + + //阻止浏览器默认行为 + EventHandler.on(document, "dragleave", preventHandler) + EventHandler.on(document, 'drop', preventHandler) + EventHandler.on(document, 'dragenter', preventHandler) + EventHandler.on(document, 'dragover', preventHandler) + + EventHandler.on(el, 'drop', e => { + try { + //获取文件对象 + const fileList = e.dataTransfer.files + + //检测是否是拖拽文件到页面的操作 + if (fileList.length === 0) { + return false + } + + inputFile.files = e.dataTransfer.files + const event = new Event('change', { bubbles: true }) + inputFile.dispatchEvent(event) + } catch (e) { + console.error(e) } - } + }) - _init() { - this._inputFile = this._element.querySelector('[type="file"]') - this._setListeners() - } + EventHandler.on(el, 'paste', e => { + inputFile.files = e.clipboardData.files + const event = new Event('change', { bubbles: true }) + inputFile.dispatchEvent(event) + }) - _setListeners() { - EventHandler.on(this._element, 'click', this._config.browserClass, () => { - this._inputFile.click() - }) - - //阻止浏览器默认行为 - EventHandler.on(document, "dragleave", e => { - e.preventDefault() - }) - EventHandler.on(document, 'drop', e => { - e.preventDefault() - }) - EventHandler.on(document, 'dragenter', e => { - e.preventDefault() - }) - EventHandler.on(document, 'dragover', e => { - e.preventDefault() - }) - - EventHandler.on(this._element, 'drop', e => { - try { - //获取文件对象 - const fileList = e.dataTransfer.files - - //检测是否是拖拽文件到页面的操作 - if (fileList.length === 0) { - return false; - } - - this._inputFile.files = e.dataTransfer.files; - const event = new Event('change', { bubbles: true }); - this._inputFile.dispatchEvent(event); - } catch (e) { - console.error(e); - } - }) - - EventHandler.on(this._element, 'paste', e => { - this._inputFile.files = e.clipboardData.files; - const event = new Event('change', { bubbles: true }); - this._inputFile.dispatchEvent(event); - }); - - EventHandler.on(this._element, 'click', '.btn-zoom', e => { - if (!this._previewer) { - this._previewer = Data.get(this._config.previewerId) - } - const button = e.delegateTarget - const buttons = [...this._element.querySelectorAll('.btn-zoom')] - this._previewer.viewer.show(buttons.indexOf(button)) - }) - } - - _execute(args) { - const tooltipId = args[0] - const method = args[1] - if (method === 'disposeTooltip' && tooltipId) { - const element = document.getElementById(tooltipId) - if (element) { - const tooltip = bootstrap.Tooltip.getInstance(element) - if (tooltip) { - tooltip.dispose() - } - } + EventHandler.on(el, 'click', '.btn-zoom', e => { + if (!upload.viewer) { + const previewId = el.getAttribute('data-bb-previewer-id') + const viewEl = document.getElementById(previewId) + upload.viewer = Viewer.init(viewEl, []) + upload.viewEl = viewEl } - } + const button = e.delegateTarget + const buttons = [...el.querySelectorAll('.btn-zoom')] + upload.viewer.updatePrevList([...el.querySelectorAll('.upload-body img')].map(v => v.src)) + upload.viewer.show(buttons.indexOf(button)) + }) +} - _dispose() { - EventHandler.off(this._element, 'click', this._config.browserClass) - EventHandler.off(document, 'dragleave'); - EventHandler.off(document, 'drop'); - EventHandler.off(document, 'dragenter'); - EventHandler.off(document, 'dragover'); - EventHandler.off(this._element, 'drop'); - EventHandler.off(this._element, 'paste'); +export function dispose(id) { + const upload = Data.get(id) + Data.remove(id) + + const el = upload.el + const preventHandler = upload.preventHandler + if (upload) { + if (upload.viewer) { + upload.viewer.dispose(upload.viewEl) + } + EventHandler.off(el, 'click') + EventHandler.off(el, 'drop') + EventHandler.off(el, 'paste') + EventHandler.off(document, 'dragleave', preventHandler) + EventHandler.off(document, 'drop', preventHandler) + EventHandler.off(document, 'dragenter', preventHandler) + EventHandler.off(document, 'dragover', preventHandler) } } diff --git a/src/BootstrapBlazor/wwwroot/modules/viewer.js b/src/BootstrapBlazor/wwwroot/modules/viewer.js index f65caab22..5f07e6477 100644 --- a/src/BootstrapBlazor/wwwroot/modules/viewer.js +++ b/src/BootstrapBlazor/wwwroot/modules/viewer.js @@ -36,6 +36,10 @@ export default { viewer.el.classList.add('show') } + viewer.updatePrevList = prevList => { + viewer.prevList = prevList + } + viewer.resetImage = () => { viewer.prevImg.classList.add('transition-none') viewer.prevImg.style.transform = 'scale(1) rotate(0deg)' diff --git a/test/UnitTest/Components/UploadTest.cs b/test/UnitTest/Components/UploadTest.cs index ebc68f619..1564c7fc7 100644 --- a/test/UnitTest/Components/UploadTest.cs +++ b/test/UnitTest/Components/UploadTest.cs @@ -755,11 +755,40 @@ public class UploadTest : BootstrapBlazorTestBase }); }); - var button = cut.FindAll(".btn-secondary"); - await cut.InvokeAsync(() => button[1].Click()); + var button = cut.Find(".btn-download"); + await cut.InvokeAsync(() => button.Click()); Assert.True(clicked); } + [Fact] + public async Task CardUpload_ShowZoom() + { + var clicked = false; + var cut = Context.RenderComponent>(pb => + { + pb.Add(a => a.ShowZoomButton, true); + pb.Add(a => a.OnZoomAsync, file => + { + clicked = true; + return Task.CompletedTask; + }); + pb.Add(a => a.DefaultFileList, new List() + { + new UploadFile() { FileName = "Test-File1.text" } + }); + }); + + var button = cut.Find(".btn-zoom"); + await cut.InvokeAsync(() => button.Click()); + Assert.True(clicked); + + cut.SetParametersAndRender(pb => + { + pb.Add(a => a.ShowZoomButton, false); + }); + cut.DoesNotContain("btn-zoom"); + } + [Fact] public void CardUpload_ValidateForm_Ok() {