Przeglądaj źródła

优化导出,新增txt格式导出

Suxue 1 rok temu
rodzic
commit
f8a06fa000

+ 2 - 4
Interface/ExportInterface.cs → Export/ExportInterface.cs

@@ -5,15 +5,13 @@ using System.Text;
 using System.Threading.Tasks;
 using WechatBakTool.Model;
 
-namespace WechatBakTool.Interface
+namespace WechatBakTool.Export
 {
     public interface IExport
     {
-        void InitTemplate(WXSession session);
-        void InitTemplate(WXContact session);
+        void InitTemplate(WXContact session,string path);
         void SetMsg(WXUserReader reader, WXContact session);
         void SetEnd();
         void Save(string path = "", bool append = false);
-
     }
 }

+ 12 - 12
HtmlExport.cs → Export/HtmlExport.cs

@@ -6,34 +6,35 @@ using System.IO;
 using System.Linq;
 using System.Text;
 using System.Threading.Tasks;
-using WechatBakTool.Interface;
 using WechatBakTool.Model;
 using System.Xml;
 
-namespace WechatBakTool
+namespace WechatBakTool.Export
 {
     public class HtmlExport : IExport
     {
         private string HtmlBody = "";
         private WXSession? Session = null;
+        private string Path = "";
         public void InitTemplate(WXSession session)
         {
             Session = session;
-            HtmlBody = "<!DOCTYPE html><html><head><meta charset=\"utf-8\"><title>溯雪微信聊天记录备份工具</title><style>p{margin:0px;}.msg{padding-bottom:10px;}.nickname{font-size:10px;}.content{font-size:14px;}</style></head><body>";
+            HtmlBody = "<!DOCTYPE html><html><head><meta charset=\"utf-8\"><title>WechatBakTool</title><style>p{margin:0px;}.msg{padding-bottom:10px;}.nickname{font-size:10px;}.content{font-size:14px;}</style></head><body>";
 
             HtmlBody += string.Format("<div class=\"msg\"><p class=\"nickname\"><b>与 {0}({1}) 的聊天记录</b></p>", Session.NickName, Session.UserName);
             HtmlBody += string.Format("<div class=\"msg\"><p class=\"nickname\"><b>导出时间:{0}</b></p><hr/>", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
         }
 
-        public void InitTemplate(WXContact contact)
+        public void InitTemplate(WXContact contact, string p)
         {
+            Path = p;
             WXSession session = new WXSession();
             session.NickName = contact.NickName;
             session.UserName = contact.UserName;
             InitTemplate(session);
         }
 
-        public void Save(string path = "",bool append = false)
+        public void Save(string path = "", bool append = false)
         {
             if (!append)
             {
@@ -51,7 +52,7 @@ namespace WechatBakTool
             HtmlBody += "</body></html>";
         }
 
-        public void SetMsg(WXUserReader reader,WXContact contact)
+        public void SetMsg(WXUserReader reader, WXContact contact)
         {
             if (Session == null)
                 throw new Exception("请初始化模版:Not Use InitTemplate");
@@ -88,13 +89,13 @@ namespace WechatBakTool
                     }
                     HtmlBody += string.Format("<p class=\"content\"><video controls style=\"max-height:300px;max-width:300px;\"><source src=\"{0}\" type=\"video/mp4\" /></video></p></div>", path);
                 }
-                else if(msg.Type== 49)
+                else if (msg.Type == 49)
                 {
                     using (var decoder = LZ4Decoder.Create(true, 64))
                     {
                         byte[] target = new byte[10240];
                         int res = 0;
-                        if(msg.CompressContent != null)
+                        if (msg.CompressContent != null)
                             res = LZ4Codec.Decode(msg.CompressContent, 0, msg.CompressContent.Length, target, 0, target.Length);
 
                         byte[] data = target.Skip(0).Take(res).ToArray();
@@ -104,15 +105,15 @@ namespace WechatBakTool
                             xml = xml.Replace("\n", "");
                             XmlDocument xmlObj = new XmlDocument();
                             xmlObj.LoadXml(xml);
-                            if(xmlObj.DocumentElement != null)
+                            if (xmlObj.DocumentElement != null)
                             {
                                 string title = "";
                                 string appName = "";
                                 string url = "";
                                 XmlNodeList? findNode = xmlObj.DocumentElement.SelectNodes("/msg/appmsg/title");
-                                if(findNode != null)
+                                if (findNode != null)
                                 {
-                                    if(findNode.Count > 0)
+                                    if (findNode.Count > 0)
                                     {
                                         title = findNode[0]!.InnerText;
                                     }
@@ -137,7 +138,6 @@ namespace WechatBakTool
 
                             }
                         }
-
                     }
                 }
                 else if (msg.Type == 34)

+ 146 - 0
Export/TXTExport.cs

@@ -0,0 +1,146 @@
+using K4os.Compression.LZ4.Encoders;
+using K4os.Compression.LZ4;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Xml;
+using WechatBakTool.Model;
+
+namespace WechatBakTool.Export
+{
+    public class TXTExport : IExport
+    {
+        private WXContact? Contact { get; set; } = null;
+        private string Path { get; set; } = "";
+        public void InitTemplate(WXContact contact,string p)
+        {
+            Contact = contact;
+            Path = p;
+            if (File.Exists(Path))
+            {
+                File.WriteAllText(Path, "");
+            }
+            File.AppendAllText(Path, string.Format("WechatBakTool\n"));
+            File.AppendAllText(Path, string.Format("与 {0} 的聊天记录\n", Contact.NickName));
+            File.AppendAllText(Path, string.Format("导出时间:{0}\n", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")));
+            File.AppendAllText(Path, string.Format("=================================================================\n\n\n"));
+        }
+
+        void IExport.Save(string path, bool append)
+        {
+            
+        }
+
+        void IExport.SetEnd()
+        {
+            
+        }
+
+        public void SetMsg(WXUserReader reader, WXContact session)
+        {
+            if (Contact == null)
+                throw new Exception("请初始化模版:Not Use InitTemplate");
+
+            List<WXMsg>? msgList = reader.GetWXMsgs(Contact.UserName);
+            if (msgList == null)
+                throw new Exception("获取消息失败,请确认数据库读取正常");
+
+            msgList.Sort((x, y) => x.CreateTime.CompareTo(y.CreateTime));
+
+            foreach (var msg in msgList)
+            {
+                string txtMsg = "";
+                switch (msg.Type)
+                {
+                    case 1:
+                        txtMsg = msg.StrContent;
+                        break;
+                    case 3:
+                        txtMsg = "[图片]";
+                        break;
+                    case 34:
+                        txtMsg = "[语音]";
+                        break;
+                    case 43:
+                        txtMsg = "[视频]";
+                        break;
+                    case 49:
+                        try
+                        {
+                            using (var decoder = LZ4Decoder.Create(true, 64))
+                            {
+                                byte[] target = new byte[10240];
+                                int res = 0;
+                                if (msg.CompressContent != null)
+                                    res = LZ4Codec.Decode(msg.CompressContent, 0, msg.CompressContent.Length, target, 0, target.Length);
+
+                                byte[] data = target.Skip(0).Take(res).ToArray();
+                                string xml = Encoding.UTF8.GetString(data);
+                                if (!string.IsNullOrEmpty(xml))
+                                {
+                                    xml = xml.Replace("\n", "");
+                                    XmlDocument xmlObj = new XmlDocument();
+                                    xmlObj.LoadXml(xml);
+                                    if (xmlObj.DocumentElement != null)
+                                    {
+                                        string title = "";
+                                        string appName = "";
+                                        string url = "";
+                                        XmlNodeList? findNode = xmlObj.DocumentElement.SelectNodes("/msg/appmsg/title");
+                                        if (findNode != null)
+                                        {
+                                            if (findNode.Count > 0)
+                                            {
+                                                title = findNode[0]!.InnerText;
+                                            }
+                                        }
+                                        findNode = xmlObj.DocumentElement.SelectNodes("/msg/appmsg/sourcedisplayname");
+                                        if (findNode != null)
+                                        {
+                                            if (findNode.Count > 0)
+                                            {
+                                                appName = findNode[0]!.InnerText;
+                                            }
+                                        }
+                                        findNode = xmlObj.DocumentElement.SelectNodes("/msg/appmsg/url");
+                                        if (findNode != null)
+                                        {
+                                            if (findNode.Count > 0)
+                                            {
+                                                url = findNode[0]!.InnerText;
+                                            }
+                                        }
+                                        txtMsg = string.Format("{0},标题:{1},链接:{2}", appName, title, url);
+                                    }
+                                    else
+                                    {
+                                        txtMsg = "[分享链接出错了]";
+                                    }
+                                }
+                                else
+                                {
+                                    txtMsg = "[分享链接出错了]";
+                                }
+                            }
+                        }
+                        catch
+                        {
+                            txtMsg = "[分享链接出错了]";
+                        }
+                        break;
+                }
+                string row = string.Format("{2} | {0}:{1}\n", msg.IsSender ? "我" : msg.NickName, txtMsg, TimeStampToDateTime(msg.CreateTime).ToString("yyyy-MM-dd HH:mm:ss"));
+                File.AppendAllText(Path, row);
+            }
+        }
+
+        private static DateTime TimeStampToDateTime(long timeStamp, bool inMilli = false)
+        {
+            DateTimeOffset dateTimeOffset = inMilli ? DateTimeOffset.FromUnixTimeMilliseconds(timeStamp) : DateTimeOffset.FromUnixTimeSeconds(timeStamp);
+            return dateTimeOffset.LocalDateTime;
+        }
+    }
+}

+ 6 - 0
Model/Common.cs

@@ -21,6 +21,12 @@ namespace WechatBakTool.Model
         public string ResPath { get; set; } = "";
     }
 
+    public class ExportItem
+    {
+        public string Name { get; set; } = "";
+        public int Value { get; set; }
+    }
+
     public class UserInfo
     {
         public string UserName { get; set; } = "";

+ 108 - 27
Pages/Workspace.xaml

@@ -8,6 +8,111 @@
       d:DesignHeight="450" d:DesignWidth="720"
       Title="Workspace" Background="White">
     <Page.Resources>
+        <Style TargetType="ToggleButton" x:Key="ComboxStyleBtn">
+            <Setter Property="Template">
+                <Setter.Value>
+                    <ControlTemplate>
+                        <!--下拉按钮内部背景色-->
+                        <Border x:Name="Back" Background="{Binding Background, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}" BorderThickness="1,0,0,0" CornerRadius="0,3,3,0">
+                            <!--下拉按钮内边框-->
+                            <Path Name="PathFill" Fill="{Binding Foreground, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}"  Width="10" Height="6" StrokeThickness="0" Data="M5,0 L10,10 L0,10 z" RenderTransformOrigin="0.5,0.5" Stretch="Fill">
+                                <Path.RenderTransform>
+                                    <TransformGroup>
+                                        <ScaleTransform/>
+                                        <SkewTransform/>
+                                        <RotateTransform Angle="180"/>
+                                        <TranslateTransform/>
+                                    </TransformGroup>
+                                </Path.RenderTransform>
+                            </Path>
+                        </Border>
+                        <ControlTemplate.Triggers>
+                            <Trigger Property="IsMouseOver" Value="True">
+                                <Setter TargetName="PathFill" Property="Fill" Value="White"></Setter>
+                            </Trigger>
+                        </ControlTemplate.Triggers>
+                    </ControlTemplate>
+                </Setter.Value>
+            </Setter>
+            <Style.Triggers>
+                <DataTrigger Binding="{Binding Path=IsEnabled, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}" Value="False">
+                    <Setter Property="Background" Value="#efefef" />
+                    <Setter Property="Opacity" Value="1" />
+                    <Setter Property="Foreground" Value="#000000" />
+                </DataTrigger>
+                <DataTrigger Binding="{Binding Path=IsEnabled, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}" Value="True">
+                    <Setter Property="Background" Value="#2775b6" />
+                    <Setter Property="Foreground" Value="#ffffff" />
+                </DataTrigger>
+            </Style.Triggers>
+        </Style>
+        <Style x:Key="ButtonStyle" TargetType="{x:Type Button}">
+
+        </Style>
+        <!--Combox-->
+        <Style TargetType="ComboBox" x:Key="ComboBoxStyle">
+            <Setter Property="ItemContainerStyle">
+                <Setter.Value>
+                    <!--ComBoxItem-->
+                    <Style TargetType="ComboBoxItem">
+                        <Setter Property="MinHeight" Value="22"></Setter>
+                        <Setter Property="MinWidth" Value="60"></Setter>
+                        <Setter Property="Foreground" Value="White"/>
+                        <Setter Property="Template">
+                            <Setter.Value>
+                                <ControlTemplate TargetType="ComboBoxItem">
+                                    <Border Name="Back" Background="Transparent"  BorderThickness="0">
+                                        <ContentPresenter VerticalAlignment="Center" HorizontalAlignment="Left" Margin="10,0,0,0" ></ContentPresenter>
+                                    </Border>
+                                    <ControlTemplate.Triggers>
+                                        <Trigger Property="IsMouseOver" Value="True">
+                                            <Setter TargetName="Back" Property="Background" Value="#BB2775b6"></Setter>
+                                        </Trigger>
+                                        <!--下拉框背景色-->
+                                        <Trigger Property="IsHighlighted" Value="True">
+                                            <Setter TargetName="Back" Property="Background" Value="#2775b6"></Setter>
+                                        </Trigger>
+                                    </ControlTemplate.Triggers>
+                                </ControlTemplate>
+                            </Setter.Value>
+                        </Setter>
+                    </Style>
+                </Setter.Value>
+            </Setter>
+            <Setter Property="Template">
+                <Setter.Value>
+                    <ControlTemplate TargetType="ComboBox">
+                        <Grid>
+                            <Grid.ColumnDefinitions>
+                                <ColumnDefinition Width="0.7*"/>
+                                <ColumnDefinition Width="0.3*" MaxWidth="30"/>
+                            </Grid.ColumnDefinitions>
+                            <!--文字区域背景和边线样式-->
+
+                            <Border Grid.Column="0" BorderThickness="1" BorderBrush="{Binding Background, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}" CornerRadius="3,0,0,3">
+                                <Button Name="export" Click="Export_Click" Background="{Binding Background, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}" Foreground="White"  Grid.Column="0" BorderThickness="0" Content="{TemplateBinding Text}" HorizontalContentAlignment="Left" VerticalContentAlignment="Center" Padding="8,0,0,0">
+                                </Button>
+                            </Border>
+                            <!--右侧下拉button设置-->
+                            <Border Grid.Column="1"  BorderThickness="0">
+                                <ToggleButton BorderThickness="3" Style="{StaticResource ComboxStyleBtn}" IsChecked="{Binding Path=IsDropDownOpen, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}" ClickMode="Press"></ToggleButton>
+                            </Border>
+                            <!--弹出popup整体设置-->
+                            <Popup IsOpen="{TemplateBinding IsDropDownOpen}" Placement="Bottom" x:Name="Popup" Focusable="False" AllowsTransparency="False" PopupAnimation="Slide" >
+                                <!--弹出popup边框-->
+                                <Border CornerRadius="3" BorderThickness="0" MaxHeight="{TemplateBinding MaxDropDownHeight}" MinWidth="{TemplateBinding ActualWidth}" x:Name="DropDown" SnapsToDevicePixels="True">
+                                    <!--下拉幕布边界背景设置 MaxHeight="{TemplateBinding MaxDropDownHeight}"-->
+                                    <ScrollViewer Margin="0,0,0,0" Background="Gray"  SnapsToDevicePixels="True" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto" BorderBrush="Gray" BorderThickness="0" >
+                                        <!--StackPanel 用于显示子级,方法是将 IsItemsHost 设置为 True-->
+                                        <StackPanel IsItemsHost="True" KeyboardNavigation.DirectionalNavigation="Contained" Background="#BB2775b6" />
+                                    </ScrollViewer>
+                                </Border>
+                            </Popup>
+                        </Grid>
+                    </ControlTemplate>
+                </Setter.Value>
+            </Setter>
+        </Style>
         <Style x:Key="RepeatButtonTransparent" TargetType="{x:Type RepeatButton}">
             <Setter Property="OverridesDefaultStyle" Value="true"/>
             <Setter Property="Background" Value="#2775b6"/>
@@ -73,24 +178,6 @@
         </DataTemplate>
     </Page.Resources>
     <Grid>
-        <!--
-        <Label FontSize="20" Margin="30,15" Content="工作台" HorizontalAlignment="Left" VerticalAlignment="Top" />
-        <Label Name="lab_status" Margin="30,45,0,0" HorizontalAlignment="Left" VerticalAlignment="Top" Content="当前工作区还未解密,请先解密。"></Label>
-        <Button Name="btn_decrypt" Margin="35,80,0,0" Width="60" Height="30" Content="解密" Foreground="White" Background="#2775b6" BorderThickness="0" HorizontalAlignment="Left" VerticalAlignment="Top" Click="btn_decrypt_Click">
-            <Button.Resources>
-                <Style TargetType="{x:Type Border}">
-                    <Setter Property="CornerRadius" Value="3" />
-                </Style>
-            </Button.Resources>
-        </Button>
-        <Button Name="btn_read" Margin="125,80,0,0" Width="60" Height="30" Content="读取" IsEnabled="False" Foreground="White" Background="#2775b6" BorderThickness="0" HorizontalAlignment="Left" VerticalAlignment="Top" Click="btn_read_Click">
-            <Button.Resources>
-                <Style TargetType="{x:Type Border}">
-                    <Setter Property="CornerRadius" Value="3" />
-                </Style>
-            </Button.Resources>
-        </Button>
-        -->
         <TextBox Name="txt_find_user" Padding="10,0" Height="30" VerticalAlignment="Top" VerticalContentAlignment="Center" FontSize="14" HorizontalAlignment="Left" Width="230" BorderThickness="0,0,10,1" BorderBrush="#2775b6" TextChanged="txt_find_user_TextChanged" GotFocus="txt_find_user_GotFocus" Text="{Binding SearchString, Mode=TwoWay}" />
         <ListView Margin="0,30,0,0" Background="Transparent" HorizontalAlignment="Left" Width="230" Name="list_users" ItemTemplate="{DynamicResource ListViewItemContentTemplate}" BorderThickness="0,0,1,0" BorderBrush="#2775b6" SelectionChanged="list_users_SelectionChanged" ItemsSource="{Binding Contacts}">
             <ListView.Resources>
@@ -130,21 +217,15 @@
         <ListView x:Name="list_msg" Margin="230,60,0,60" Background="Transparent" BorderThickness="0,1,0,1" BorderBrush="#BB2775b6" ItemTemplate="{DynamicResource MsgText}">
             
         </ListView>
-        <Button Name="btn_export" Width="90" Height="30" Content="导出HTML" BorderBrush="Transparent" BorderThickness="0" Background="#2775b6" Foreground="White" HorizontalAlignment="Right" VerticalAlignment="Bottom" Margin="20,15" Click="btn_export_Click" IsEnabled="{Binding SelectContact}">
-            <Button.Resources>
-                <Style TargetType="{x:Type Border}">
-                    <Setter Property="CornerRadius" Value="3"/>
-                </Style>
-            </Button.Resources>
-        </Button>
-        <Button x:Name="btn_open_workspace" Width="80" Height="30" Content="打开文件夹" BorderBrush="Transparent" BorderThickness="0" Background="#2775b6" Foreground="White" HorizontalAlignment="Right" VerticalAlignment="Bottom" Margin="0,0,390,15" Click="btn_open_workspace_Click">
+        <ComboBox Name="cb_export" Width="120" Height="30" Style="{StaticResource ComboBoxStyle}" HorizontalAlignment="Right" VerticalAlignment="Bottom" Margin="30,15" ItemsSource="{Binding ExportItems}" SelectedItem="{Binding SelectExportItem}" DisplayMemberPath="Name" SelectedValuePath="Value" IsEnabled="{Binding SelectContact}" Background="#2775b6" />
+        <Button x:Name="btn_open_workspace" Width="80" Height="30" Style="{StaticResource  ButtonStyle}" Content="打开文件夹" BorderBrush="Transparent" BorderThickness="0" Background="#2775b6" Foreground="White" HorizontalAlignment="Right" VerticalAlignment="Bottom" Margin="0,0,390,15" Click="btn_open_workspace_Click">
             <Button.Resources>
                 <Style TargetType="{x:Type Border}">
                     <Setter Property="CornerRadius" Value="3"/>
                 </Style>
             </Button.Resources>
         </Button>
-        <Button x:Name="btn_analyse" Width="80" Height="30" Content="旧版消息工具" BorderBrush="Transparent" BorderThickness="0" Background="#2775b6" Foreground="White" HorizontalAlignment="Right" VerticalAlignment="Bottom" Margin="0,0,292,15" Click="btn_analyse_Click" >
+        <Button x:Name="btn_analyse" Width="80" Height="30" Style="{StaticResource  ButtonStyle}" Content="旧版消息工具" BorderBrush="Transparent" BorderThickness="0" Background="#2775b6" Foreground="White" HorizontalAlignment="Right" VerticalAlignment="Bottom" Margin="0,0,292,15" Click="btn_analyse_Click" >
             <Button.Resources>
                 <Style TargetType="{x:Type Border}">
                     <Setter Property="CornerRadius" Value="3"/>

+ 45 - 5
Pages/Workspace.xaml.cs

@@ -16,7 +16,7 @@ using System.Windows.Input;
 using System.Windows.Media;
 using System.Windows.Media.Imaging;
 using System.Windows.Navigation;
-using WechatBakTool.Interface;
+using WechatBakTool.Export;
 using WechatBakTool.Model;
 using WechatBakTool.ViewModel;
 
@@ -31,6 +31,11 @@ namespace WechatBakTool.Pages
         private WorkspaceViewModel ViewModel { get; set; } = new WorkspaceViewModel();
         public Workspace()
         {
+            ViewModel.ExportItems = new System.Collections.ObjectModel.ObservableCollection<ExportItem> {
+                new ExportItem(){ Name="导出为HTML",Value=1 },
+                new ExportItem(){ Name="导出为TXT",Value=2 },
+            };
+            ViewModel.SelectExportItem = ViewModel.ExportItems[0];
             InitializeComponent();
             DataContext = ViewModel;
             UserBakConfig? config = Main2.CurrentUserBakConfig;
@@ -91,12 +96,11 @@ namespace WechatBakTool.Pages
                 MessageBox.Show("请选择联系人", "错误");
                 return;
             }
-            IExport export = new HtmlExport();
-            export.InitTemplate(ViewModel.WXContact);
+            string path = Path.Combine(Main2.CurrentUserBakConfig!.UserWorkspacePath, ViewModel.WXContact.UserName + ".txt");
+            IExport export = new TXTExport();
+            export.InitTemplate(ViewModel.WXContact, path);
             export.SetMsg(UserReader, ViewModel.WXContact);
             export.SetEnd();
-            //string path = UserReader.GetSavePath(wXContact);
-            string path = Path.Combine(Main2.CurrentUserBakConfig!.UserWorkspacePath, ViewModel.WXContact.UserName + ".html");
             export.Save(path);
             MessageBox.Show("导出完成");
         }
@@ -116,5 +120,41 @@ namespace WechatBakTool.Pages
             Analyse analyse = new Analyse(Main2.CurrentUserBakConfig, UserReader);
             analyse.Show();
         }
+
+        private void Export_Click(object sender, RoutedEventArgs e)
+        {
+            if (ViewModel.WXContact == null || UserReader == null)
+            {
+                MessageBox.Show("请选择联系人", "错误");
+                return;
+            }
+            if(ViewModel.SelectExportItem == null)
+            {
+                MessageBox.Show("请选择导出方式", "错误");
+                return;
+            }
+            string path = Path.Combine(Main2.CurrentUserBakConfig!.UserWorkspacePath, ViewModel.WXContact.UserName);
+            IExport export;
+            if (ViewModel.SelectExportItem.Value == 2)
+            {
+                path += ".txt";
+                export = new TXTExport();
+            }
+            else
+            {
+                path += ".html";
+                export = new HtmlExport();
+            }
+            export.InitTemplate(ViewModel.WXContact, path);
+            export.SetMsg(UserReader, ViewModel.WXContact);
+            export.SetEnd();
+            export.Save(path);
+            MessageBox.Show("导出完成");
+        }
+
+        private void ComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
+        {
+
+        }
     }
 }

+ 4 - 0
README.md

@@ -20,6 +20,10 @@
 > [!NOTE]
 > 反馈群:815054692<br/>
 > 如果觉得不错,欢迎右上角点个star!这是对作者的鼓励,谢谢!<br/>
+
+> [!NOTE]
+> 本分支为项目开发分支,变动较为频繁且可能不可用<br/>
+> 如果你希望观察作者的开发动态,可以参考这个分支。<br/>
 <br/>
 
 ### 免责声明

+ 6 - 0
ViewModel/WorkspaceViewModel.cs

@@ -34,6 +34,12 @@ namespace WechatBakTool.ViewModel
         [ObservableProperty]
         private ObservableCollection<WXContact>? contacts;
 
+        [ObservableProperty]
+        private ObservableCollection<ExportItem>? exportItems;
+
+        [ObservableProperty]
+        private ExportItem? selectExportItem;
+
         private string searchString = "";
         public string SearchString
         {

+ 3 - 3
WechatBakTool.csproj

@@ -6,9 +6,9 @@
     <Nullable>enable</Nullable>
     <UseWPF>true</UseWPF>
     <AllowUnsafeBlocks>True</AllowUnsafeBlocks>
-    <AssemblyVersion>0.9.0.0</AssemblyVersion>
-    <FileVersion>0.9.0.0</FileVersion>
-    <Version>0.9.0.0</Version>
+    <AssemblyVersion>0.9.1.0</AssemblyVersion>
+    <FileVersion>0.9.1.0</FileVersion>
+    <Version>0.9.1.0</Version>
   </PropertyGroup>
 
   <ItemGroup>