mirror of
https://gitee.com/LongbowEnterprise/BootstrapBlazor.git
synced 2024-12-02 12:09:59 +08:00
!852 feat(#I2C63D): add ClickToUpload mode in Upload component
* docs: 增加点击上传模式示例文件 * docs: 增加点击上传示例文档 * feat: 增加点击上传功能 * chore: 打包脚本不输出颜色 * feat: 增加单击上传模式 * chore: 增加 bundle&minifier Cli tool * docs: 更新 Upload 示例文件 * docs: 更新 Table 示例文件 * style: upload 适配移动端
This commit is contained in:
parent
e97d8eff21
commit
841d83b2fa
@ -11,20 +11,19 @@
|
|||||||
<DetailRowTemplate>
|
<DetailRowTemplate>
|
||||||
<Tab>
|
<Tab>
|
||||||
<TabItem Text="明细数据">
|
<TabItem Text="明细数据">
|
||||||
@{
|
@{
|
||||||
// 此段代码为提高性能
|
// 此段代码为提高性能
|
||||||
var cacheKey = context.Name ?? "";
|
var cacheKey = context.Name ?? "";
|
||||||
var DetailDataSource = Enumerable.Empty<DetailRow>
|
var DetailDataSource = Enumerable.Empty<DetailRow>();
|
||||||
();
|
if (Cache.ContainsKey(cacheKey))
|
||||||
if (Cache.ContainsKey(cacheKey))
|
{
|
||||||
{
|
DetailDataSource = Cache[cacheKey];
|
||||||
DetailDataSource = Cache[cacheKey];
|
}
|
||||||
}
|
else
|
||||||
else
|
{
|
||||||
{
|
DetailDataSource = GetDetailRowsByName(cacheKey).ToList();
|
||||||
DetailDataSource = GetDetailRowsByName(cacheKey).ToList();
|
Cache.Add(cacheKey, DetailDataSource);
|
||||||
Cache.Add(cacheKey, DetailDataSource);
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
<Table TItem="DetailRow" IsBordered="true" ShowToolbar="false" Items="@DetailDataSource">
|
<Table TItem="DetailRow" IsBordered="true" ShowToolbar="false" Items="@DetailDataSource">
|
||||||
<TableColumns Context="Detail">
|
<TableColumns Context="Detail">
|
||||||
|
@ -1 +1,15 @@
|
|||||||
<Upload />
|
<Upload ShowDeleteButton="true" OnChange="@OnFileChange" OnDelete="@OnFileDelete"></Upload>
|
||||||
|
|
||||||
|
@code {
|
||||||
|
private Task<string> OnFileChange(InputFileChangeEventArgs args)
|
||||||
|
{
|
||||||
|
Trace?.Log($"{args.File.Name} 上传成功");
|
||||||
|
return Task.FromResult("");
|
||||||
|
}
|
||||||
|
|
||||||
|
private Task<bool> OnFileDelete(string fileName)
|
||||||
|
{
|
||||||
|
Trace?.Log($"{fileName} 成功移除");
|
||||||
|
return Task.FromResult(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1 +1 @@
|
|||||||
<Upload ShowPreview="true"></Upload>
|
<Upload Style="UploadStyle.ClickToUpload" OnDelete="@(fileName => Task.FromResult(true))"></Upload>
|
||||||
|
@ -1 +1,15 @@
|
|||||||
<Upload IsCircle="true"></Upload>
|
@{
|
||||||
|
var DefaultFileList = new List<UploadFile>();
|
||||||
|
DefaultFileList.AddRange(new[]
|
||||||
|
{
|
||||||
|
new UploadFile()
|
||||||
|
{
|
||||||
|
FileName = "default1.jpg"
|
||||||
|
},
|
||||||
|
new UploadFile()
|
||||||
|
{
|
||||||
|
FileName = "default2.jpg"
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
<Upload Style="UploadStyle.ClickToUpload" OnDelete="@(fileName => Task.FromResult(true))" DefaultFileList="@DefaultFileList"></Upload>
|
||||||
|
@ -4,15 +4,6 @@
|
|||||||
|
|
||||||
<h4>通过点击或者拖拽上传文件</h4>
|
<h4>通过点击或者拖拽上传文件</h4>
|
||||||
|
|
||||||
<p>
|
|
||||||
由于上传组件上传文件的大小受后台程序、反向代理等诸多因素影响,相关文章请参阅 <a href="https://gitee.com/LongbowEnterprise/BootstrapBlazor/wikis/Upload%20%E7%BB%84%E4%BB%B6%E6%B3%A8%E6%84%8F%E4%BA%8B%E9%A1%B9?sort_id=2166580" target="_blank">Upload 组件注意事项</a>
|
|
||||||
<br>出于服务器安全考虑,以下组件示例中上传文件均限制为文件类型必须为 <code>image/*</code> ,文件大小被限制为不能超过 <code>20 MB</code>
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<Tips>
|
|
||||||
<p>本组件正在开发中,此页面为测试功能时使用</p>
|
|
||||||
</Tips>
|
|
||||||
|
|
||||||
<Block Title="基本用法" Introduction="与其他表单组件一起使用,显示文件名称,点击 <b>浏览</b> 按钮后选择文件并上传;通过设置 <code>ShowRemoveButton</code> 参数,显示 <b>删除</b> 按钮,点击删除按钮时回调 <code>OnDelete</code> 委托方法" CodeFile="upload.1.html">
|
<Block Title="基本用法" Introduction="与其他表单组件一起使用,显示文件名称,点击 <b>浏览</b> 按钮后选择文件并上传;通过设置 <code>ShowRemoveButton</code> 参数,显示 <b>删除</b> 按钮,点击删除按钮时回调 <code>OnDelete</code> 委托方法" CodeFile="upload.1.html">
|
||||||
<div class="form-inline">
|
<div class="form-inline">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
@ -33,6 +24,35 @@
|
|||||||
<Logger @ref="Trace" />
|
<Logger @ref="Trace" />
|
||||||
</Block>
|
</Block>
|
||||||
|
|
||||||
|
<Block Title="点击上传" Introduction="经典款式,用户点击按钮弹出文件选择框。" CodeFile="upload.2.html">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-12 col-sm-6">
|
||||||
|
<Upload Style="UploadStyle.ClickToUpload" OnDelete="@(fileName => Task.FromResult(true))"></Upload>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Block>
|
||||||
|
|
||||||
|
<Block Title="已上传文件列表" Introduction="使用 <code>DefaultFileList</code> 设置已上传的内容" CodeFile="upload.3.html">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-12 col-sm-6">
|
||||||
|
@{
|
||||||
|
var DefaultFileList = new List<UploadFile>();
|
||||||
|
DefaultFileList.AddRange(new[]
|
||||||
|
{
|
||||||
|
new UploadFile()
|
||||||
|
{
|
||||||
|
FileName = "default1.jpg"
|
||||||
|
},
|
||||||
|
new UploadFile()
|
||||||
|
{
|
||||||
|
FileName = "default2.jpg"
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
<Upload Style="UploadStyle.ClickToUpload" OnDelete="@(fileName => Task.FromResult(true))" DefaultFileList="@DefaultFileList"></Upload>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Block>
|
||||||
<!--<Block Title="预览后上传" Introduction="通过设置 <code>ShowPreview</code> 属性开启本地预览,点击上传按钮开始上传" CodeFile="upload.2.html">
|
<!--<Block Title="预览后上传" Introduction="通过设置 <code>ShowPreview</code> 属性开启本地预览,点击上传按钮开始上传" CodeFile="upload.2.html">
|
||||||
<p>仅允许上传 <code>images/*</code> 格式文件,文件大小不能超过 <code>20 MB</code></p>
|
<p>仅允许上传 <code>images/*</code> 格式文件,文件大小不能超过 <code>20 MB</code></p>
|
||||||
<Upload AllowFileType="@AllowFiles" MaxFileLength="20971520" ShowPreview="true" OnUploaded="@OnPreviewUpload"></Upload>
|
<Upload AllowFileType="@AllowFiles" MaxFileLength="20971520" ShowPreview="true" OnUploaded="@OnPreviewUpload"></Upload>
|
||||||
|
@ -5,16 +5,32 @@
|
|||||||
@if (Style == UploadStyle.Normal)
|
@if (Style == UploadStyle.Normal)
|
||||||
{
|
{
|
||||||
<div class="input-group">
|
<div class="input-group">
|
||||||
<input type="text" class="form-control" id="@Id" readonly placeholder="@PlaceHolder" value="@FileName" />
|
<input type="text" class="form-control" id="@Id" readonly placeholder="@PlaceHolder" value="@(UploadFiles.FirstOrDefault()?.FileName)" />
|
||||||
<div class="input-group-append">
|
<div class="input-group-append">
|
||||||
@if (ShowDeleteButton)
|
@if (ShowDeleteButton)
|
||||||
{
|
{
|
||||||
<Button class="@RemoveButtonClassString" IsDisabled="@IsDeleteButtonDisabled" Icon="@DeleteButtonIcon" Text="@DeleteButtonText" OnClick="@OnFileDelete" />
|
<Button class="@RemoveButtonClassString" IsDisabled="@IsDeleteButtonDisabled" Icon="@DeleteButtonIcon" Text="@DeleteButtonText" OnClick="@(e => OnFileDelete(UploadFiles.FirstOrDefault()))" />
|
||||||
}
|
}
|
||||||
@*<Button class="@UploadButtonClassString" IsDisabled="@IsDisabled" Icon="@UploadButtonIcon" Text="@UploadButtonText" />*@
|
|
||||||
<Button class="@BrowserButtonClassString" IsDisabled="@IsDisabled" Icon="@BrowserButtonIcon" Text="@BrowserButtonText" OnClick="@OnFileBrowser" />
|
<Button class="@BrowserButtonClassString" IsDisabled="@IsDisabled" Icon="@BrowserButtonIcon" Text="@BrowserButtonText" OnClick="@OnFileBrowser" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<InputFile hidden accept="@AllowFileType" OnChange="OnFileChange" />
|
||||||
|
}
|
||||||
|
else if (Style == UploadStyle.ClickToUpload)
|
||||||
|
{
|
||||||
|
<Button class="@BrowserButtonClassString" IsDisabled="@IsDisabled" Icon="@BrowserButtonIcon" Text="@BrowserButtonText" />
|
||||||
|
<div class="upload-body">
|
||||||
|
@foreach (var item in UploadFiles)
|
||||||
|
{
|
||||||
|
<div class="@GetUploadItemClassString(item)">
|
||||||
|
<i class="@GetFileIcon(item)"></i>
|
||||||
|
<span>@item.FileName</span>
|
||||||
|
<i class="fa fa-check-circle-o text-success"></i>
|
||||||
|
<i class="fa fa-trash-o text-danger" @onclick:stopPropagation @onclick="@(e => OnFileDelete(item))"></i>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
<InputFile hidden multiple="@MultipleString" accept="@AllowFileType" OnChange="OnFileChange" />
|
||||||
}
|
}
|
||||||
@*<div class="upload-item">
|
@*<div class="upload-item">
|
||||||
<div class="@PreviewClassString" style="@PrevStyleString">
|
<div class="@PreviewClassString" style="@PrevStyleString">
|
||||||
@ -35,5 +51,4 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>*@
|
</div>*@
|
||||||
<InputFile hidden multiple="@MultipleString" accept="@AllowFileType" OnChange="OnFileChange" />
|
|
||||||
</div>
|
</div>
|
||||||
|
@ -11,6 +11,7 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics.CodeAnalysis;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace BootstrapBlazor.Components
|
namespace BootstrapBlazor.Components
|
||||||
@ -57,6 +58,15 @@ namespace BootstrapBlazor.Components
|
|||||||
.AddClass($"height: {Width}px;", !IsStack && IsCircle)
|
.AddClass($"height: {Width}px;", !IsStack && IsCircle)
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
|
private string? GetUploadItemClassString(UploadFile item) => CssBuilder.Default("upload-item")
|
||||||
|
.AddClass("is-valid", item.Code == 0)
|
||||||
|
.AddClass("is-invalid", item.Code != 0)
|
||||||
|
.Build();
|
||||||
|
|
||||||
|
private string? GetFileIcon(UploadFile item) => CssBuilder.Default("fa")
|
||||||
|
.AddClass("fa-file-text-o", true)
|
||||||
|
.Build();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 获得/设置 圆形进度半径
|
/// 获得/设置 圆形进度半径
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -94,7 +104,10 @@ namespace BootstrapBlazor.Components
|
|||||||
.AddClass(BrowserButtonClass)
|
.AddClass(BrowserButtonClass)
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
private bool IsDeleteButtonDisabled => IsDisabled || string.IsNullOrEmpty(FileName);
|
private bool IsDeleteButtonDisabled => IsDisabled || !UploadFiles.Any();
|
||||||
|
|
||||||
|
[NotNull]
|
||||||
|
private List<UploadFile>? UploadFiles { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 获得/设置 上传组件模式 默认为 Normal 正常模式多用于表单中
|
/// 获得/设置 上传组件模式 默认为 Normal 正常模式多用于表单中
|
||||||
@ -157,10 +170,11 @@ namespace BootstrapBlazor.Components
|
|||||||
public string Icon { get; set; } = "fa fa-cloud-upload";
|
public string Icon { get; set; } = "fa fa-cloud-upload";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 获得/设置 上传文件名
|
/// 获得/设置 已上传文件集合
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public string? FileName { get; set; }
|
[NotNull]
|
||||||
|
public List<UploadFile>? DefaultFileList { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 获得/设置 是否显示预览 默认不预览
|
/// 获得/设置 是否显示预览 默认不预览
|
||||||
@ -306,6 +320,15 @@ namespace BootstrapBlazor.Components
|
|||||||
ResetText ??= Localizer[nameof(ResetText)];
|
ResetText ??= Localizer[nameof(ResetText)];
|
||||||
FileTooLargeText ??= Localizer[nameof(FileTooLargeText)];
|
FileTooLargeText ??= Localizer[nameof(FileTooLargeText)];
|
||||||
AllowFileTypeErrorMessage ??= Localizer[nameof(AllowFileTypeErrorMessage)];
|
AllowFileTypeErrorMessage ??= Localizer[nameof(AllowFileTypeErrorMessage)];
|
||||||
|
|
||||||
|
if (Style != UploadStyle.Normal)
|
||||||
|
{
|
||||||
|
UploadFiles ??= new List<UploadFile>();
|
||||||
|
}
|
||||||
|
|
||||||
|
UploadFiles ??= new List<UploadFile>();
|
||||||
|
|
||||||
|
if (DefaultFileList != null) UploadFiles.AddRange(DefaultFileList);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -322,42 +345,45 @@ namespace BootstrapBlazor.Components
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task OnFileDelete()
|
private async Task OnFileDelete(UploadFile? item)
|
||||||
{
|
{
|
||||||
if (OnDelete != null && !string.IsNullOrEmpty(FileName))
|
if (OnDelete != null && item != null)
|
||||||
{
|
{
|
||||||
var ret = await OnDelete(FileName);
|
var ret = await OnDelete(item.File?.Name ?? item.FileName);
|
||||||
if (ret)
|
if (ret)
|
||||||
{
|
{
|
||||||
FileName = null;
|
UploadFiles.Remove(item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Task OnFileBrowser()
|
private Task OnFileBrowser()
|
||||||
{
|
{
|
||||||
FileName = "";
|
// 单文件模式
|
||||||
|
UploadFiles.Clear();
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task OnFileChange(InputFileChangeEventArgs args)
|
private async Task OnFileChange(InputFileChangeEventArgs args)
|
||||||
{
|
{
|
||||||
FileName = args.File.Name;
|
var file = new UploadFile()
|
||||||
|
|
||||||
if (OnChange == null)
|
|
||||||
{
|
{
|
||||||
var format = args.File.ContentType;
|
FileName = args.File.Name,
|
||||||
var imageFile = await args.File.RequestImageFileAsync(format, 640, 480);
|
Size = args.File.Size,
|
||||||
|
File = args.File
|
||||||
|
};
|
||||||
|
UploadFiles.Add(file);
|
||||||
|
|
||||||
using var fileStream = imageFile.OpenReadStream();
|
if (Style == UploadStyle.Normal)
|
||||||
using var memoryStream = new MemoryStream();
|
{
|
||||||
await fileStream.CopyToAsync(memoryStream);
|
if (OnChange != null)
|
||||||
|
{
|
||||||
ImageUrl = $"data:{format};base64,{Convert.ToBase64String(memoryStream.ToArray())}";
|
ImageUrl = await OnChange(args);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else if (Style == UploadStyle.ClickToUpload)
|
||||||
{
|
{
|
||||||
ImageUrl = await OnChange(args);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,6 +2,8 @@
|
|||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
// Website: https://www.blazor.zone or https://argozhang.github.io/
|
// Website: https://www.blazor.zone or https://argozhang.github.io/
|
||||||
|
|
||||||
|
using Microsoft.AspNetCore.Components.Forms;
|
||||||
|
|
||||||
namespace BootstrapBlazor.Components
|
namespace BootstrapBlazor.Components
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -38,5 +40,10 @@ namespace BootstrapBlazor.Components
|
|||||||
/// 获得/设置 错误信息
|
/// 获得/设置 错误信息
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string? Error { get; set; }
|
public string? Error { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获得/设置 上传文件实例
|
||||||
|
/// </summary>
|
||||||
|
internal IBrowserFile? File { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,12 +2,6 @@
|
|||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
// Website: https://www.blazor.zone or https://argozhang.github.io/
|
// Website: https://www.blazor.zone or https://argozhang.github.io/
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace BootstrapBlazor.Components
|
namespace BootstrapBlazor.Components
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -18,8 +12,11 @@ namespace BootstrapBlazor.Components
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 正常模式
|
/// 正常模式
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Normal
|
Normal,
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 点击上传
|
||||||
|
/// </summary>
|
||||||
|
ClickToUpload,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
File diff suppressed because one or more lines are too long
@ -3640,9 +3640,52 @@ input:disabled,
|
|||||||
/*end calendar*/
|
/*end calendar*/
|
||||||
|
|
||||||
/*upload*/
|
/*upload*/
|
||||||
.form-inline .upload {
|
@media (min-width: 576px) {
|
||||||
width: calc(100% - 104px);
|
.form-inline .upload {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@media (min-width: 768px) {
|
||||||
|
.form-inline .upload {
|
||||||
|
width: calc(100% - 104px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.upload .upload-body {
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.upload .upload-body .upload-item {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
padding: 3px 5px;
|
||||||
|
border-radius: 3px;
|
||||||
|
transition: background-color .3s linear;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.upload .upload-body .upload-item:not(:last-child) {
|
||||||
|
margin-bottom: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.upload .upload-body .upload-item:hover {
|
||||||
|
background-color: #ebeef5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.upload .upload-body .upload-item:hover .fa-trash-o {
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.upload .upload-body .upload-item span {
|
||||||
|
flex: 1;
|
||||||
|
padding: 0 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.upload .upload-body .upload-item .fa-trash-o,
|
||||||
|
.upload .upload-body .upload-item:hover .fa-check-circle-o {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
/*end upload*/
|
/*end upload*/
|
||||||
|
|
||||||
/*divider*/
|
/*divider*/
|
||||||
|
File diff suppressed because one or more lines are too long
@ -43,4 +43,4 @@ var QRCode;!function(){function a(a){this.mode=c.MODE_8BIT_BYTE,this.data=a,this
|
|||||||
$file.trigger('click');
|
$file.trigger('click');
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
})(jQuery);
|
})(jQuery);
|
||||||
|
Loading…
Reference in New Issue
Block a user