Merge remote-tracking branch 'origin/dev2.0' into dev2.0
commit
dab37de4d3
|
|
@ -0,0 +1,487 @@
|
||||||
|
using HeBianGu.Base.WpfBase;
|
||||||
|
using HeBianGu.Control.Explorer;
|
||||||
|
using Hopetry.Services;
|
||||||
|
using Minio.DataModel.Args;
|
||||||
|
using Minio;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Windows;
|
||||||
|
using Microsoft.Extensions.Configuration;
|
||||||
|
using Minio.ApiEndpoints;
|
||||||
|
using System.Windows.Threading;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Windows.Media.Imaging;
|
||||||
|
using System.Windows.Media;
|
||||||
|
|
||||||
|
namespace Hopetry.Provider.Behaviors
|
||||||
|
{
|
||||||
|
public class ExplorerMinIOBehavior : Behavior<Explorer>
|
||||||
|
{
|
||||||
|
#region 依赖属性
|
||||||
|
|
||||||
|
public bool UseMinIO
|
||||||
|
{
|
||||||
|
get { return (bool)GetValue(UseMinIOProperty); }
|
||||||
|
set { SetValue(UseMinIOProperty, value); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public static readonly DependencyProperty UseMinIOProperty =
|
||||||
|
DependencyProperty.Register("UseMinIO", typeof(bool), typeof(ExplorerMinIOBehavior),
|
||||||
|
new PropertyMetadata(false, OnUseMinIOChanged));
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region 字段和初始化
|
||||||
|
private IMinioClient _minioClient;
|
||||||
|
private bool _isLocalHistoryRefresh;
|
||||||
|
protected override void OnAttached()
|
||||||
|
{
|
||||||
|
base.OnAttached();
|
||||||
|
|
||||||
|
InitializeMinIOClient();
|
||||||
|
|
||||||
|
// 监听路径变化
|
||||||
|
var pathDescriptor = DependencyPropertyDescriptor.FromProperty(
|
||||||
|
Explorer.CurrentPathProperty, typeof(Explorer));
|
||||||
|
pathDescriptor.AddValueChanged(AssociatedObject, OnCurrentPathChanged);
|
||||||
|
|
||||||
|
// 监听历史记录变化
|
||||||
|
var historyDescriptor = DependencyPropertyDescriptor.FromProperty(
|
||||||
|
Explorer.HistoryProperty, typeof(Explorer));
|
||||||
|
historyDescriptor.AddValueChanged(AssociatedObject, OnHistoryChanged);
|
||||||
|
|
||||||
|
// 初始加载MinIO内容
|
||||||
|
if (UseMinIO)
|
||||||
|
{
|
||||||
|
Dispatcher.BeginInvoke((Action)(() =>
|
||||||
|
{
|
||||||
|
var initialPath = string.IsNullOrEmpty(AssociatedObject.CurrentPath) ?
|
||||||
|
"" : AssociatedObject.CurrentPath;
|
||||||
|
|
||||||
|
RefreshMinIOPath(initialPath);
|
||||||
|
|
||||||
|
// 更新CurrentPath如果为空
|
||||||
|
if (string.IsNullOrEmpty(AssociatedObject.CurrentPath))
|
||||||
|
{
|
||||||
|
AssociatedObject.CurrentPath = initialPath;
|
||||||
|
}
|
||||||
|
}), DispatcherPriority.Loaded);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnDetaching()
|
||||||
|
{
|
||||||
|
// Clean up event handlers
|
||||||
|
var pathDescriptor = DependencyPropertyDescriptor.FromProperty(
|
||||||
|
Explorer.CurrentPathProperty, typeof(Explorer));
|
||||||
|
pathDescriptor.RemoveValueChanged(AssociatedObject, OnCurrentPathChanged);
|
||||||
|
|
||||||
|
var historyDescriptor = DependencyPropertyDescriptor.FromProperty(
|
||||||
|
Explorer.HistoryProperty, typeof(Explorer));
|
||||||
|
historyDescriptor.RemoveValueChanged(AssociatedObject, OnHistoryChanged);
|
||||||
|
|
||||||
|
base.OnDetaching();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region 事件处理
|
||||||
|
|
||||||
|
private static void OnUseMinIOChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
||||||
|
{
|
||||||
|
var behavior = (ExplorerMinIOBehavior)d;
|
||||||
|
if ((bool)e.NewValue && behavior.AssociatedObject != null)
|
||||||
|
{
|
||||||
|
behavior.Dispatcher.BeginInvoke((Action)(() =>
|
||||||
|
{
|
||||||
|
behavior.RefreshMinIOPath(behavior.AssociatedObject.CurrentPath);
|
||||||
|
}), DispatcherPriority.ContextIdle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnCurrentPathChanged(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
if (UseMinIO)
|
||||||
|
{
|
||||||
|
RefreshMinIOPath(AssociatedObject.CurrentPath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnHistoryChanged(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
// Track when history is changed externally
|
||||||
|
_isLocalHistoryRefresh = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region MinIO 操作
|
||||||
|
|
||||||
|
private void InitializeMinIOClient()
|
||||||
|
{
|
||||||
|
var builder = new ConfigurationBuilder()
|
||||||
|
.SetBasePath(Directory.GetCurrentDirectory())
|
||||||
|
.AddJsonFile("global.json", optional: false, reloadOnChange: true);
|
||||||
|
// 构建配置
|
||||||
|
var config = builder.Build();
|
||||||
|
|
||||||
|
_minioClient = new MinioClient()
|
||||||
|
.WithEndpoint(config["Minio:Endpoint"])
|
||||||
|
.WithCredentials(config["Minio:AccessKey"], config["Minio:SecretKey"])
|
||||||
|
.Build();
|
||||||
|
}
|
||||||
|
|
||||||
|
private async void RefreshMinIOPath(string path)
|
||||||
|
{
|
||||||
|
if (AssociatedObject == null || _minioClient == null) return;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
AssociatedObject.IsEnabled = false;
|
||||||
|
AssociatedObject.Cursor = System.Windows.Input.Cursors.Wait;
|
||||||
|
|
||||||
|
var items = await GetMinIOItemsAsync(path);
|
||||||
|
AssociatedObject.ItemsSource = items.ToObservable();
|
||||||
|
|
||||||
|
// Update history if this wasn't triggered by a history navigation
|
||||||
|
if (!_isLocalHistoryRefresh && !string.IsNullOrEmpty(path))
|
||||||
|
{
|
||||||
|
UpdateHistory(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
_isLocalHistoryRefresh = false;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
MessageBox.Show($"Error accessing MinIO: {ex.Message}", "Error",
|
||||||
|
MessageBoxButton.OK, MessageBoxImage.Error);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
AssociatedObject.IsEnabled = true;
|
||||||
|
AssociatedObject.Cursor = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<IEnumerable<SystemInfoModel>> GetMinIOItemsAsync(string path)
|
||||||
|
{
|
||||||
|
var items = new List<SystemInfoModel>();
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(path))
|
||||||
|
{
|
||||||
|
// List all buckets
|
||||||
|
var buckets = await _minioClient.ListBucketsAsync();
|
||||||
|
items.AddRange(buckets.Buckets.Select(b =>
|
||||||
|
new MinIODirectoryModel(new MinIODirectoryInfo(b.Name,null,true, b.CreationDateDateTime))));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// List objects in a bucket/path
|
||||||
|
var parts = path.Split(new[] { '/' }, 2);
|
||||||
|
var bucketName = parts[0];
|
||||||
|
var prefix = parts.Length > 1 ? parts[1] : null;
|
||||||
|
|
||||||
|
var args = new ListObjectsArgs()
|
||||||
|
.WithBucket(bucketName)
|
||||||
|
.WithPrefix(prefix ?? "")
|
||||||
|
.WithRecursive(false);
|
||||||
|
//var ss= new ListObjectsArgs()
|
||||||
|
// .WithBucket("demo")
|
||||||
|
// .WithPrefix("women")
|
||||||
|
// .WithRecursive(false);
|
||||||
|
|
||||||
|
var observable = _minioClient.ListObjectsEnumAsync(args);
|
||||||
|
//var observable1 = _minioClient.ListObjectsEnumAsync(ss);
|
||||||
|
|
||||||
|
await foreach (var item in observable)
|
||||||
|
{
|
||||||
|
if (item.IsDir)
|
||||||
|
{
|
||||||
|
items.Add(new MinIODirectoryModel(
|
||||||
|
new MinIODirectoryInfo(bucketName, item.Key, false, DateTime.Now)));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
string size = item.Size < 1024 * 1024 ?
|
||||||
|
$"{Math.Ceiling((decimal)item.Size / 1024)}KB" :
|
||||||
|
$"{Math.Ceiling((decimal)item.Size / (1024 * 1024))}MB";
|
||||||
|
items.Add(new MinIOFileModel(
|
||||||
|
new MinIOFileInfo(bucketName, item.Key, size, item.LastModifiedDateTime)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return items;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateHistory(string path)
|
||||||
|
{
|
||||||
|
var parts = path.Split(new[] { '/' }, 2);
|
||||||
|
var bucketName = parts[0];
|
||||||
|
var prefix = parts.Length > 1 ? parts[1] : null;
|
||||||
|
|
||||||
|
var dirInfo = new MinIODirectoryInfo(bucketName, prefix,false, DateTime.Now);
|
||||||
|
var historyItem = new DirectoryModel(dirInfo);
|
||||||
|
|
||||||
|
// Avoid duplicates
|
||||||
|
if (AssociatedObject.History.FirstOrDefault()?.Model?.FullName != path)
|
||||||
|
{
|
||||||
|
AssociatedObject.History.Insert(0, historyItem);
|
||||||
|
AssociatedObject.History = AssociatedObject.History
|
||||||
|
.Take(ExplorerSetting.Instance.HistCapacity)
|
||||||
|
.ToObservable();
|
||||||
|
}
|
||||||
|
|
||||||
|
AssociatedObject.HistorySelectedItem = AssociatedObject.History.FirstOrDefault();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region 图标处理
|
||||||
|
|
||||||
|
private static readonly Dictionary<string, System.Drawing.Icon> _iconCache = new Dictionary<string, System.Drawing.Icon>();
|
||||||
|
private const string DefaultFontFamily = "Segoe MDL2 Assets";
|
||||||
|
private const double DefaultIconSize = 16;
|
||||||
|
|
||||||
|
public static System.Drawing.Icon GetIconForMinIOItem(string name, bool isDirectory, bool isBucket = false)
|
||||||
|
{
|
||||||
|
var cacheKey = $"{(isBucket ? "bucket" : (isDirectory ? "folder" : Path.GetExtension(name).ToLower()))}";
|
||||||
|
|
||||||
|
if (!_iconCache.TryGetValue(cacheKey, out var icon))
|
||||||
|
{
|
||||||
|
icon = LoadMinIOIcon(name, isDirectory, isBucket);
|
||||||
|
_iconCache[cacheKey] = icon;
|
||||||
|
}
|
||||||
|
|
||||||
|
return icon;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static System.Drawing.Icon LoadMinIOIcon(string name, bool isDirectory, bool isBucket)
|
||||||
|
{
|
||||||
|
// 获取字体图标字符
|
||||||
|
string iconChar = GetFontIconChar(name, isDirectory, isBucket);
|
||||||
|
|
||||||
|
// 创建字体图标ImageSource
|
||||||
|
var imageSource = CreateFontIconImageSource(iconChar);
|
||||||
|
|
||||||
|
// 转换为Icon
|
||||||
|
return ConvertRenderTargetBitmapToIcon(imageSource as RenderTargetBitmap);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static System.Drawing.Icon ConvertRenderTargetBitmapToIcon(RenderTargetBitmap renderTargetBitmap)
|
||||||
|
{
|
||||||
|
// 将 RenderTargetBitmap 转为 Bitmap
|
||||||
|
var bitmap = new System.Drawing.Bitmap(
|
||||||
|
renderTargetBitmap.PixelWidth,
|
||||||
|
renderTargetBitmap.PixelHeight,
|
||||||
|
System.Drawing.Imaging.PixelFormat.Format32bppPArgb);
|
||||||
|
|
||||||
|
var data = bitmap.LockBits(
|
||||||
|
new System.Drawing.Rectangle(0, 0, bitmap.Width, bitmap.Height),
|
||||||
|
System.Drawing.Imaging.ImageLockMode.WriteOnly,
|
||||||
|
System.Drawing.Imaging.PixelFormat.Format32bppPArgb);
|
||||||
|
|
||||||
|
renderTargetBitmap.CopyPixels(
|
||||||
|
System.Windows.Int32Rect.Empty,
|
||||||
|
data.Scan0,
|
||||||
|
data.Height * data.Stride,
|
||||||
|
data.Stride);
|
||||||
|
|
||||||
|
bitmap.UnlockBits(data);
|
||||||
|
|
||||||
|
// 从 Bitmap 创建 Icon
|
||||||
|
var iconHandle = bitmap.GetHicon();
|
||||||
|
return System.Drawing.Icon.FromHandle(iconHandle);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string GetFontIconChar(string name, bool isDirectory, bool isBucket)
|
||||||
|
{
|
||||||
|
// 使用Segoe MDL2 Assets字体中的字符代码
|
||||||
|
if (isBucket)
|
||||||
|
{
|
||||||
|
return "\ue7c3"; // Cloud icon
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isDirectory)
|
||||||
|
{
|
||||||
|
return "\ue8b7"; // Folder icon
|
||||||
|
}
|
||||||
|
|
||||||
|
// 按文件类型返回不同图标
|
||||||
|
string extension = Path.GetExtension(name)?.ToLower();
|
||||||
|
|
||||||
|
switch (extension)
|
||||||
|
{
|
||||||
|
case ".pdf": return "\uea90";
|
||||||
|
case ".jpg":
|
||||||
|
case ".png":
|
||||||
|
case ".jpeg":
|
||||||
|
case ".gif":
|
||||||
|
case ".bmp":
|
||||||
|
case ".svg":
|
||||||
|
return "\ueb9f"; // Picture icon
|
||||||
|
case ".doc":
|
||||||
|
case ".docx":
|
||||||
|
return "\ue8a5"; // Word document icon
|
||||||
|
case ".xls":
|
||||||
|
case ".xlsx":
|
||||||
|
return "\ue8a6"; // Excel document icon
|
||||||
|
case ".ppt":
|
||||||
|
case ".pptx":
|
||||||
|
return "\ue8a7"; // PowerPoint icon
|
||||||
|
case ".zip":
|
||||||
|
case ".rar":
|
||||||
|
case ".7z":
|
||||||
|
return "\ue7b8"; // Zip folder icon
|
||||||
|
case ".txt":
|
||||||
|
case ".log":
|
||||||
|
return "\ue8ab"; // Text document icon
|
||||||
|
case ".mp3":
|
||||||
|
case ".wav":
|
||||||
|
case ".flac":
|
||||||
|
return "\ue8d6"; // Audio icon
|
||||||
|
case ".mp4":
|
||||||
|
case ".avi":
|
||||||
|
case ".mov":
|
||||||
|
case ".wmv":
|
||||||
|
return "\ue8b2"; // Video icon
|
||||||
|
case ".exe":
|
||||||
|
case ".msi":
|
||||||
|
return "\ue756"; // Application icon
|
||||||
|
case ".html":
|
||||||
|
case ".htm":
|
||||||
|
return "\ue842"; // HTML icon
|
||||||
|
case ".cs":
|
||||||
|
case ".cpp":
|
||||||
|
case ".js":
|
||||||
|
case ".java":
|
||||||
|
return "\ue9a2"; // Code icon
|
||||||
|
default:
|
||||||
|
return "\ue7c4"; // Default document icon
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ImageSource CreateFontIconImageSource(
|
||||||
|
string iconChar,
|
||||||
|
string fontFamily = DefaultFontFamily,
|
||||||
|
double fontSize = DefaultIconSize,
|
||||||
|
System.Windows.Media.Brush foreground = null)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var textBlock = new System.Windows.Controls.TextBlock
|
||||||
|
{
|
||||||
|
Text = iconChar,
|
||||||
|
FontFamily = new System.Windows.Media.FontFamily(fontFamily),
|
||||||
|
FontSize = fontSize,
|
||||||
|
Foreground = foreground ?? System.Windows.Media.Brushes.Black,
|
||||||
|
HorizontalAlignment = System.Windows.HorizontalAlignment.Center,
|
||||||
|
VerticalAlignment = System.Windows.VerticalAlignment.Center
|
||||||
|
};
|
||||||
|
|
||||||
|
// 计算实际需要的尺寸
|
||||||
|
textBlock.Measure(new System.Windows.Size(double.PositiveInfinity, double.PositiveInfinity));
|
||||||
|
textBlock.Arrange(new System.Windows.Rect(textBlock.DesiredSize));
|
||||||
|
|
||||||
|
var renderTargetBitmap = new RenderTargetBitmap(
|
||||||
|
(int)Math.Ceiling(textBlock.ActualWidth),
|
||||||
|
(int)Math.Ceiling(textBlock.ActualHeight),
|
||||||
|
96, 96, PixelFormats.Pbgra32);
|
||||||
|
|
||||||
|
renderTargetBitmap.Render(textBlock);
|
||||||
|
renderTargetBitmap.Freeze();
|
||||||
|
|
||||||
|
return renderTargetBitmap;
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
// 回退到默认图标
|
||||||
|
return CreateFontIconImageSource("\ue7c4", fontFamily, fontSize, foreground);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
|
||||||
|
#region MinIO 模型类
|
||||||
|
|
||||||
|
public interface IMinIOFileInfo : ISystemFileInfo
|
||||||
|
{
|
||||||
|
string BucketName { get; }
|
||||||
|
bool IsDirectory { get; }
|
||||||
|
bool IsBucket { get; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class MinIOFileInfo : IMinIOFileInfo, IFileInfo
|
||||||
|
{
|
||||||
|
public MinIOFileInfo(string bucketName, string key, string size, DateTime? lastModified)
|
||||||
|
{
|
||||||
|
BucketName = bucketName;
|
||||||
|
FullName = $"{bucketName}/{key}";
|
||||||
|
Name = Path.GetFileName(key);
|
||||||
|
Size = size;
|
||||||
|
LastModified = lastModified;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string BucketName { get; }
|
||||||
|
public bool IsDirectory => false;
|
||||||
|
public bool IsBucket => false;
|
||||||
|
public string Name { get; }
|
||||||
|
public string FullName { get; }
|
||||||
|
public string Size { get; }
|
||||||
|
public DateTime? LastModified { get; }
|
||||||
|
public DateTime? LastWriteTime => LastModified;
|
||||||
|
public FileAttributes Attributes => FileAttributes.Normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class MinIODirectoryInfo : IMinIOFileInfo, IDirectoryInfo
|
||||||
|
{
|
||||||
|
public MinIODirectoryInfo(string bucketName, string key, bool isBucket, DateTime creationDate)
|
||||||
|
{
|
||||||
|
BucketName = bucketName;
|
||||||
|
FullName = string.IsNullOrEmpty(key) ? bucketName : $"{bucketName}/{key}";
|
||||||
|
Name = string.IsNullOrEmpty(key) ? bucketName : key.TrimEnd('/').Split('/').Last();
|
||||||
|
IsBucket = isBucket;
|
||||||
|
LastWriteTime = creationDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string BucketName { get; }
|
||||||
|
public bool IsDirectory => true;
|
||||||
|
public bool IsBucket { get; }
|
||||||
|
public string Name { get; }
|
||||||
|
public string FullName { get; }
|
||||||
|
public DateTime LastWriteTime { get; }
|
||||||
|
public FileAttributes Attributes => FileAttributes.Directory;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class MinIOFileModel : FileModel
|
||||||
|
{
|
||||||
|
public MinIOFileModel(IFileInfo model) : base(model)
|
||||||
|
{
|
||||||
|
this.Icon = "\ue7c4"; // 默认文件图标
|
||||||
|
}
|
||||||
|
|
||||||
|
public new Icon Logo => ExplorerMinIOBehavior.GetIconForMinIOItem(
|
||||||
|
this.Model.Name,
|
||||||
|
isDirectory: false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public class MinIODirectoryModel : DirectoryModel
|
||||||
|
{
|
||||||
|
public MinIODirectoryModel(IDirectoryInfo model) : base(model)
|
||||||
|
{
|
||||||
|
this.Icon = "\ue8b7"; // 默认文件夹图标
|
||||||
|
}
|
||||||
|
|
||||||
|
public new Icon Logo => ExplorerMinIOBehavior.GetIconForMinIOItem(
|
||||||
|
this.Model.Name,
|
||||||
|
isDirectory: true,
|
||||||
|
isBucket: (this.Model as IMinIOFileInfo)?.IsBucket ?? false);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
|
@ -4,6 +4,8 @@
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
xmlns:h="https://github.com/HeBianGu"
|
xmlns:h="https://github.com/HeBianGu"
|
||||||
xmlns:local="clr-namespace:HeBianGu.App.Disk"
|
xmlns:local="clr-namespace:HeBianGu.App.Disk"
|
||||||
|
xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
|
||||||
|
xmlns:behaviors="clr-namespace:Hopetry.Provider.Behaviors"
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
d:DesignHeight="450"
|
d:DesignHeight="450"
|
||||||
d:DesignWidth="800"
|
d:DesignWidth="800"
|
||||||
|
|
@ -32,15 +34,19 @@
|
||||||
<Button h:Cattach.Icon="" Content="离线下载" Style="{DynamicResource {x:Static h:ButtonKeys.Dynamic}}" />-->
|
<Button h:Cattach.Icon="" Content="离线下载" Style="{DynamicResource {x:Static h:ButtonKeys.Dynamic}}" />-->
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
|
|
||||||
<h:Explorer Margin="0,0,10,0" CurrentPath="{Binding Path, Mode=TwoWay}" Style="{DynamicResource {x:Static h:Explorer.DefaultKey}}">
|
<h:Explorer Margin="0,0,10,0" CurrentPath="{Binding CurrentMinIOPath, Mode=TwoWay}" Style="{DynamicResource {x:Static h:Explorer.DefaultKey}}">
|
||||||
<h:Interaction.Behaviors>
|
<h:Interaction.Behaviors>
|
||||||
<h:LoadAnimationBehavior End="0.05"
|
<!--<h:LoadAnimationBehavior End="0.05"
|
||||||
EndValue="1"
|
EndValue="1"
|
||||||
IsUseAll="True"
|
IsUseAll="True"
|
||||||
LoadAnimationType="Opactiy"
|
LoadAnimationType="Opactiy"
|
||||||
Split="0.02"
|
Split="0.02"
|
||||||
StartValue="0" />
|
StartValue="0" />-->
|
||||||
|
<behaviors:ExplorerMinIOBehavior UseMinIO="True" />
|
||||||
</h:Interaction.Behaviors>
|
</h:Interaction.Behaviors>
|
||||||
|
<!--<i:Interaction.Behaviors>
|
||||||
|
<behaviors:ExplorerMinIOBehavior UseMinIO="True" />
|
||||||
|
</i:Interaction.Behaviors>-->
|
||||||
|
|
||||||
<h:Explorer.Columns>
|
<h:Explorer.Columns>
|
||||||
<DataGridTemplateColumn Width="50" Header="">
|
<DataGridTemplateColumn Width="50" Header="">
|
||||||
|
|
@ -69,7 +75,7 @@
|
||||||
</DataGridTemplateColumn>
|
</DataGridTemplateColumn>
|
||||||
|
|
||||||
<DataGridTextColumn Width="*" Binding="{Binding Model.LastWriteTime, StringFormat='{}{0:yyyy-MM-dd HH:mm:ss}'}" Header="修改时间" />
|
<DataGridTextColumn Width="*" Binding="{Binding Model.LastWriteTime, StringFormat='{}{0:yyyy-MM-dd HH:mm:ss}'}" Header="修改时间" />
|
||||||
<DataGridTextColumn Width="*" Header="大小" />
|
<DataGridTextColumn Width="*" Binding="{Binding Model.Size}" Header="大小" />
|
||||||
</h:Explorer.Columns>
|
</h:Explorer.Columns>
|
||||||
</h:Explorer>
|
</h:Explorer>
|
||||||
</DockPanel>
|
</DockPanel>
|
||||||
|
|
|
||||||
|
|
@ -23,8 +23,8 @@ namespace HeBianGu.App.Disk
|
||||||
[ViewModel("Loyout")]
|
[ViewModel("Loyout")]
|
||||||
internal class LoyoutViewModel : MvcViewModelBase
|
internal class LoyoutViewModel : MvcViewModelBase
|
||||||
{
|
{
|
||||||
private string _path;
|
|
||||||
private readonly FileUploadService _uploadService;
|
private readonly FileUploadService _uploadService;
|
||||||
|
private string _path;
|
||||||
/// <summary> 说明 </summary>
|
/// <summary> 说明 </summary>
|
||||||
public string Path
|
public string Path
|
||||||
{
|
{
|
||||||
|
|
@ -360,6 +360,7 @@ namespace HeBianGu.App.Disk
|
||||||
{
|
{
|
||||||
|
|
||||||
string bucketName = config["Minio:BucketName"];
|
string bucketName = config["Minio:BucketName"];
|
||||||
|
|
||||||
// 确保桶存在
|
// 确保桶存在
|
||||||
var beArgs = new BucketExistsArgs().WithBucket(bucketName);
|
var beArgs = new BucketExistsArgs().WithBucket(bucketName);
|
||||||
bool found = await client.BucketExistsAsync(beArgs).ConfigureAwait(false);
|
bool found = await client.BucketExistsAsync(beArgs).ConfigureAwait(false);
|
||||||
|
|
@ -432,6 +433,20 @@ namespace HeBianGu.App.Disk
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
#region 文件列表
|
||||||
|
private string _currentMinIOPath;
|
||||||
|
/// <summary> 说明 </summary>
|
||||||
|
public string CurrentMinIOPath
|
||||||
|
{
|
||||||
|
get { return _currentMinIOPath; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_currentMinIOPath = value;
|
||||||
|
RaisePropertyChanged("CurrentMinIOPath");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class DataFileViewModel : ObservableSourceViewModel<TestViewModel>
|
internal class DataFileViewModel : ObservableSourceViewModel<TestViewModel>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue